1. 01 Dec, 2015 3 commits
    • Yedidya Feldblum's avatar
      CodeMod: Use the ExceptionWrapper::with_exception variant that deduces exception types · 15e17fa2
      Yedidya Feldblum authored
      Summary: CodeMod: Use the `ExceptionWrapper::with_exception` variant that deduces exception types.
      
      Since we must specify the exception type in the lambda arg, and there is a variant of `ExceptionWrapper::with_exception` that deduces the type of the exception from the type of the lambda arg, we don't need to specify the exception type again as a template parameter anymore.
      
      Reviewed By: meyering
      
      Differential Revision: D2694895
      
      fb-gh-sync-id: 505469f9008973a315e836f356e5db97df4ec921
      15e17fa2
    • Jim Meyering's avatar
      folly/Conv.h: estimateSpaceNeeded: avoid undefined behavior · 8d56fe68
      Jim Meyering authored
      Summary: Do not negate signed numbers like INT_MIN or INTMAX_MIN, since
      that would evoke undefined behavior.  Otherwise, the test (below)
      would fail with this run-time error:
      
        [ RUN      ] Conv.Integral2String
        folly/Conv.h:521:47: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
      
      Reviewed By: markisaa
      
      Differential Revision: D2704195
      
      fb-gh-sync-id: 4036437fb972109672004163880078127e7df797
      8d56fe68
    • Yedidya Feldblum's avatar
      Avoid deprecated Singleton<T>::get() in folly/futures · d3a08687
      Yedidya Feldblum authored
      Summary: [Folly] Avoid deprecated `Singleton<T>::get()` in `folly/futures`.
      
      Changes `getTimekeeperSingleton()` to return a `shared_ptr<Timekeeper>`, and patches its call-sites.
      
      Additionally, have the call-sites keep the singleton instance alive for the duration that it is being directly used.
      
      Reviewed By: ddrcoder
      
      Differential Revision: D2702361
      
      fb-gh-sync-id: 82b72ee514dc4f2a7f7522af8b2e92b34df063d6
      d3a08687
  2. 26 Nov, 2015 3 commits
    • Andrii Grynenko's avatar
      Deprecate get_weak() · 19fb62bd
      Andrii Grynenko authored
      Summary: get_weak() is always used with .lock(), but try_get() is actually more performant than get_weak().lock().
      Using get_weak() to store a weak_ptr and keep locking is not safe in fork scenarios.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2694223
      
      fb-gh-sync-id: 908d44293ffd9b3782152d43e28d5de172d1654a
      19fb62bd
    • Yedidya Feldblum's avatar
      Fix ExceptionWrapper::with_exception to support lvalue ref functors · f0a9aafc
      Yedidya Feldblum authored
      Summary: [Folly] Fix `ExceptionWrapper::with_exception` to support lvalue ref functors.
      
      Ex:
      
          auto handler = [&](const std::runtime_error& e) { handle_runtime_error(e); };
          exception_wrapper wrap = get_some_exception_wrapper_from_context();
          wrap.with_exception(handler); // broken before this diff, fixed after
      
      Reviewed By: markisaa
      
      Differential Revision: D2698680
      
      fb-gh-sync-id: 4976ba08e3601e22891d00d79a5dae5118887b71
      f0a9aafc
    • Andrii Grynenko's avatar
      New ReadMostlySharedPtr implementation · 596aa895
      Andrii Grynenko authored
      Summary: This changes ReadMostlySharedPtr API to have 3 types: MainPtr, WeakPtr, SharedPtr. MainPtr and SharedPtr are equivalents of std::shared_ptr, and WeakPtr is an equivalent of std::weak_ptr. The only difference is that it can only be a single MainPtr, and while it's alive copying SharedPtr/WeakPtr or WeakPtr doesn't require atomic operations (and thus can be more performant than std::shared_ptr). Unlike original ReadMostlySharedPtr API, there're no thread-safety guarantees between reset() and getShared() for ReadMostlySharedPtr.
      
      ReadMostlySharedPtr can work with different RefCount implementations. This diff introduces RCURefCount (which is currently using liburcu) and TLRefCount.
      
      Reviewed By: djwatson
      
      Differential Revision: D2683572
      
      fb-gh-sync-id: a7a03af4b1cf5f81a613368c6eebe70b2eaef064
      596aa895
  3. 25 Nov, 2015 9 commits
    • Mark Isaacson's avatar
      Fix proxygen OSS build · 7ee590ed
      Mark Isaacson authored
      Summary: So far this is a speculative fix.. I am waiting to see the results from the Ubuntu machine, but I suspect this is the problem.
      
      Reviewed By: bugok
      
      Differential Revision: D2697600
      
      fb-gh-sync-id: e33d452a52c5ace2b7401d6495621ce68a5076b5
      7ee590ed
    • Giuseppe Ottaviano's avatar
      Update symlinks · 422c78be
      Giuseppe Ottaviano authored
      Summary: See D2696092
      
      Reviewed By: meyering
      
      Differential Revision: D2696360
      
      fb-gh-sync-id: 2cfa9258be899a93a58c59dae70a10fef6f457c8
      422c78be
    • Giuseppe Ottaviano's avatar
      Skip reallocation in shrink_to_fit for empty fbvector · ac06a309
      Giuseppe Ottaviano authored
      Reviewed By: philippv
      
      Differential Revision: D2696314
      
      fb-gh-sync-id: 105de2d99bb9f5ac82310e37f9302022c103befc
      ac06a309
    • Mark Isaacson's avatar
      Make folly's T_CHECK_TIMEOUT/T_CHECK_TIME_LT use SKIP() on failure · 140c62d2
      Mark Isaacson authored
      Summary: Make these more spurious failure-aware/tolerant.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2689775
      
      fb-gh-sync-id: 1a9b247b97cc3529b12f6f7b76a4af2e32822d45
      140c62d2
    • Jim Meyering's avatar
      folly/detail/ThreadLocalDetail.h: avoid UBSAN-detected memcpy abuse · f6f52f3e
      Jim Meyering authored
      Summary: [technically, the existing code is probably a no-op on
      all systems we care about, but since it is officially UB, switching
      to a more strict platform could cause trouble, so it's worth fixing]
      
      Calling memcpy with "nullptr" as 2nd argument is undefined, even when
      the third argument is zero, and causes a failure when testing with an
      UBSAN-enabled binary (-fsanitize=undefined).
      Before this change, the buck-run test below would evoke this failure:
      
        [ RUN      ] ThreadLocalPtr.BasicDestructor
        folly/detail/ThreadLocalDetail.h:533:29: runtime error: null pointer passed as argument 2, which is declared to never be null
        third-party-buck/build/glibc/include/string.h:47:45: note: nonnull attribute specified here
      
      Ironically, the failure of the target-determinator-buck_push_blocking test (due to an unrelated proxygen dep problem) would block me from landing this, so I am adding this line to override it.
      
      Reviewed By: luciang, alexshap
      
      Differential Revision: D2692625
      
      fb-gh-sync-id: 8bdc5cd2899705f39c9565d640921de1f363807d
      f6f52f3e
    • Adrien Conrath's avatar
      Remove undefined behavior in goodMallocSize() · ffe26edc
      Adrien Conrath authored
      Reviewed By: ot
      
      Differential Revision: D2695741
      
      fb-gh-sync-id: d33263c1ffa5651d66f37992ce365dae157ed449
      ffe26edc
    • Giuseppe Ottaviano's avatar
      Make goodMallocSize always use nallocx · 5d820ea6
      Giuseppe Ottaviano authored
      Summary: `goodMallocSize` is used extensively in `folly` data structures,
      especially for containers optimized for small contents, such as
      `fbstring` and `small_vector`.
      
      However, it makes the design decision to align the allocation size to
      a x86 cache line, forcing a minimum allocation size of `64` bytes,
      despite jemalloc can provide smaller size classes (8, 16, 32,
      48). This causes a large discontinuity between small contents that can
      be inlined and heap-allocated contents:
      
      - For `fbstring`, a string of 23 bytes (including terminator) occupies
        24 bytes (`sizeof(fbstring)`), a string of 24 bytes occupies 24 + 64
        + allocation overhead when it could be 24 + 32 + allocation
        overhead. The waste is more than 50%.
      
      - For `small_vector<uint32_t, 1, uint32_t>`, for instance, a vector
        with 1 element occupies 12 bytes, a vector with 2 elements occupies
        12 + 64 + allocation overhead when it could be 12 + 8 + allocation
        overhead. The waste is more than 250%.
      
      With this diff we just trust jemalloc and always use `nallocx`. If a
      data structure need cache-line alignment it should be implemented at
      its level.
      
      Reviewed By: elsteveogrande
      
      Differential Revision: D2688156
      
      fb-gh-sync-id: 46548d4a91952e7c673d4f0997c4c067e03c190d
      5d820ea6
    • Yedidya Feldblum's avatar
      A well-known instance of folly::Unit · 1f4a8221
      Yedidya Feldblum authored
      Summary: [Folly] A well-known instance of `folly::Unit`.
      
      Reviewed By: jsedgwick
      
      Differential Revision: D2693426
      
      fb-gh-sync-id: fe595abc852500275a827b4f400cfda7091a55f7
      1f4a8221
    • Yedidya Feldblum's avatar
      ExceptionWrapper::with_exception variant, deducing exception type from functor type · 085c0a8d
      Yedidya Feldblum authored
      Summary: [Folly] `ExceptionWrapper::with_exception` variant deducing exception type from functor type.
      
      From the `README.md`:
      
          // TODO(jsedgwick) infer exception type from the type of the function
      
      Reviewed By: Gownta
      
      Differential Revision: D2685579
      
      fb-gh-sync-id: 158bcd030019f28b4f392d17167ab0bd67cc1edb
      085c0a8d
  4. 24 Nov, 2015 2 commits
    • Qinfan Wu's avatar
      Add sdallocx for jemalloc · e9df6f79
      Qinfan Wu authored
      Summary: Make jemalloc's sdallocx function available in folly and allow future code to
      use sized deallocation.
      
      Reviewed By: elsteveogrande, ot
      
      Differential Revision: D2687746
      
      fb-gh-sync-id: 9ef8a16d2c63c4eb8cecab7639add423ef093c2d
      e9df6f79
    • Yedidya Feldblum's avatar
      Fix Build: folly/test/ThreadLocalTest · 442584e7
      Yedidya Feldblum authored
      Summary: [Folly] Fix Build: `folly/test/ThreadLocalTest`.
      
      The problem is that the to the shared lib used in the test is hardcoded. It's a relative path, so that's nice, but it has too many assumptions about where the build system deposits test binaries.
      
      Instead, let the code simply look for the shared lib in the same directory as the test binary. This makes fewer assumptions on the build system.
      
      Reviewed By: andriigrynenko
      
      Differential Revision: D2689047
      
      fb-gh-sync-id: 648da079b7af5bc9893709d009e577347dd4a463
      442584e7
  5. 23 Nov, 2015 5 commits
    • Haijun Zhu's avatar
      Fix HHWheelTimerTest.AtMostEveryN · aba93096
      Haijun Zhu authored
      Summary: If it takes too long to finish it is probably heavily loaded. Skip if
      so.
      
      Reviewed By: mmcduff
      
      Differential Revision: D2687346
      
      fb-gh-sync-id: 282cac7e4df361f714de1089f11b098af79b1512
      aba93096
    • Chad Parry's avatar
      Simplify an exception handler · 6bafdff6
      Chad Parry authored
      Summary: It looks like there is no reason to catch a `std::exception` and then `dynamic_cast` to a derived exception. We can just catch the derived exception directly.
      
      whatcouldgowrong4
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2677284
      
      fb-gh-sync-id: 0149e4d4aecc96257376d410f592620205441f66
      6bafdff6
    • Michael Oliver's avatar
      Benchmark std::to_string vs. folly::to<std::string> · 4b750cf3
      Michael Oliver authored
      Summary: We wanted to compare the benefits of using folly::to<std::string> directly, and decided this benchmarking might as well be contributed back to folly.  Here are the results:
      
      ```
        ============================================================================
        folly/test/ConvTest.cpp                         relative  time/iter  iters/s
        ============================================================================
        ...
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1)                                  157.88ns    6.33M
        u64ToStringFollyMeasure(1)                       212.52%    74.29ns   13.46M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12)                                 158.14ns    6.32M
        u64ToStringFollyMeasure(12)                      212.55%    74.40ns   13.44M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(123)                                152.26ns    6.57M
        u64ToStringFollyMeasure(123)                     210.95%    72.18ns   13.85M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1234)                               152.40ns    6.56M
        u64ToStringFollyMeasure(1234)                    204.82%    74.41ns   13.44M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12345)                              156.01ns    6.41M
        u64ToStringFollyMeasure(12345)                   208.90%    74.68ns   13.39M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(123456)                             178.21ns    5.61M
        u64ToStringFollyMeasure(123456)                  238.77%    74.63ns   13.40M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1234567)                            161.38ns    6.20M
        u64ToStringFollyMeasure(1234567)                 203.09%    79.46ns   12.58M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12345678)                           159.01ns    6.29M
        u64ToStringFollyMeasure(12345678)                192.42%    82.64ns   12.10M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(123456789)                          169.07ns    5.91M
        u64ToStringFollyMeasure(123456789)               203.70%    83.00ns   12.05M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1234567890)                         166.56ns    6.00M
        u64ToStringFollyMeasure(1234567890)              187.21%    88.97ns   11.24M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12345678901)                        176.22ns    5.67M
        u64ToStringFollyMeasure(12345678901)             197.57%    89.20ns   11.21M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(123456789012)                       174.74ns    5.72M
        u64ToStringFollyMeasure(123456789012)            182.52%    95.74ns   10.45M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1234567890123)                      178.47ns    5.60M
        u64ToStringFollyMeasure(1234567890123)           186.81%    95.54ns   10.47M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12345678901234)                     187.33ns    5.34M
        u64ToStringFollyMeasure(12345678901234)          184.05%   101.78ns    9.82M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(123456789012345)                    198.16ns    5.05M
        u64ToStringFollyMeasure(123456789012345)         182.48%   108.59ns    9.21M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1234567890123456)                   182.56ns    5.48M
        u64ToStringFollyMeasure(1234567890123456)        164.19%   111.19ns    8.99M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12345678901234567)                  186.80ns    5.35M
        u64ToStringFollyMeasure(12345678901234567)       162.33%   115.07ns    8.69M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(123456789012345678)                 195.08ns    5.13M
        u64ToStringFollyMeasure(123456789012345678)      165.51%   117.87ns    8.48M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(1234567890123456789)                200.27ns    4.99M
        u64ToStringFollyMeasure(1234567890123456789)     164.62%   121.65ns    8.22M
        ----------------------------------------------------------------------------
        u64ToStringClibMeasure(12345678901234567890U)              203.18ns    4.92M
        u64ToStringFollyMeasure(12345678901234567890U)   162.38%   125.13ns    7.99M
        ----------------------------------------------------------------------------
        ...
        ============================================================================
      ```
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2680998
      
      fb-gh-sync-id: 179fbd756c714c92b7230d3750af024865ecbb0a
      4b750cf3
    • Sara Golemon's avatar
      Add missing header files to folly-automake · eebb50f2
      Sara Golemon authored
      Summary: Closes https://github.com/facebook/folly/issues/304
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2685289
      
      fb-gh-sync-id: 563697fb01ee358472b9080058848d2b557ba466
      eebb50f2
    • Sara Golemon's avatar
      Fix minor typo in folly/Conv.h · f757d940
      Sara Golemon authored
      Summary: 'flating point' => 'floating point'
      
      Closes https://github.com/facebook/folly/issues/241
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2685280
      
      fb-gh-sync-id: 2e9c2b5419d0c631af4a32c5ab6b7366033ca34c
      f757d940
  6. 21 Nov, 2015 1 commit
  7. 20 Nov, 2015 5 commits
    • Lucian Grijincu's avatar
      Revert "Fix folly::ThreadLocal to work in a shared library" · 7ce0da39
      Lucian Grijincu authored
      Summary: This reverts commit 9d355f96c4fe073c889f28070d5952fa4eb007a0.
      
      build-break
      
      Reviewed By: sctaylor
      
      Differential Revision: D2680784
      
      fb-gh-sync-id: a2df233bcd3721ffbfcd6fd71ea3cabbebebd4c4
      7ce0da39
    • Haijun Zhu's avatar
      get back AsyncServerSocket's setMaxNumMessagesInQueue · 16811575
      Haijun Zhu authored
      Summary: D2613681 codemod'ed a thrift server api but it also renamed that api
      in AsyncServerSocket, which is a mistake. Fix that in AsyncServerSocket, and
      all other places that calls this api.
      
      Reviewed By: alandau, JoelMarcey
      
      Differential Revision: D2677837
      
      fb-gh-sync-id: 0d91f1a623229e99be59ca9dcd27f1330a9a1b64
      16811575
    • Anirudh Ramachandran's avatar
      Remove unnecessary resetClientHelloParsing callback in AsyncSSLSocket · 422bf874
      Anirudh Ramachandran authored
      Summary: Remove unnecessary resetClientHelloParsing callback which causes problems wiht
      Openssl 1.0.2
      
      Reviewed By: knekritz
      
      Differential Revision: D2664730
      
      fb-gh-sync-id: d1b55ae493b4c92627ad41e7bf85f1e1a777bd2b
      422bf874
    • Alexander Shaposhnikov's avatar
      Remove busy wait and support multiple wait · badc3ebe
      Alexander Shaposhnikov authored
      Summary: Remove busy wait from Future::wait.
      If future.wait(timeout) has succeded we should
      return a ready future, otherwise we should return a future
      for the final result (not necessarily ready).
      
      Reviewed By: yfeldblum
      
      Differential Revision: D2646860
      
      fb-gh-sync-id: 62671d09073ad86e84df8c9257e961d2a8c2a339
      badc3ebe
    • Delyan Kratunov's avatar
      Expose move result from LockFreeRingBuffer::Cursor · 587e4b4d
      Delyan Kratunov authored
      Summary: Without feedback that a `moveForward` or `moveBackward` did nothing, a user
      cannot implement this idiom safely:
      
      ```
      while(rb.tryRead(entry, cursor)) {
        doSomething(entry);
        cursor.moveBackward();
      }
      ```
      
      In the case where the ring buffer has not overflowed and slot 0 is still
      available, the reader will get stuck at it (read it continuously) until
      the buffer overflows.
      
      This diff allows the above example to become:
      
      ```
      while(rb.tryRead(entry, cursor)) {
        doSomething(etnry);
        if (!cursor.moveBackward()) {
          break;
        }
      }
      ```
      
      Reviewed By: bryceredd
      
      Differential Revision: D2674975
      
      fb-gh-sync-id: a0c5857daf186ef19e203f90acc2145590f85c3b
      587e4b4d
  8. 19 Nov, 2015 3 commits
    • Giuseppe Ottaviano's avatar
      Fix usingJEMalloc with Clang · 78022b6e
      Giuseppe Ottaviano authored
      Summary: Clang is too clever and in some contexts optimizes away the `malloc`, but we rely on a side-effect. Declaring the variable as static forces it to call `malloc`. We could free the pointer relying on the fact that the lambda is guaranteed to be called only once, but I feel more comfortable just leaking it (LSan won't complain).
      
      Reviewed By: philippv
      
      Differential Revision: D2674769
      
      fb-gh-sync-id: 1153a3ca226c6b7aa64c453bd61b036dcbf3ffcc
      78022b6e
    • Anton Likhtarov's avatar
      Fix invalid DCHECK · 2fa98577
      Anton Likhtarov authored
      Summary: There's a race between insert() and erase(): as soon as insert()
      releases the lock (swaps kLockedKey_ with the actual key), an erase() might
      jump in and invalidate the key.
      
      As far as I can tell, this bug existed since the beginning.
      
      Reviewed By: nbronson
      
      Differential Revision: D2673099
      
      fb-gh-sync-id: 4721893d2ad4836e11acc0fb4ecb0dd7b2b69be1
      2fa98577
    • Andrii Grynenko's avatar
      Fix folly::ThreadLocal to work in a shared library · f2daf056
      Andrii Grynenko authored
      Reviewed By: bmaurer
      
      Differential Revision: D2667499
      
      fb-gh-sync-id: 463f86752240bd88761910de934ba25d6e62fafe
      f2daf056
  9. 18 Nov, 2015 1 commit
  10. 17 Nov, 2015 1 commit
  11. 16 Nov, 2015 1 commit
  12. 15 Nov, 2015 1 commit
  13. 13 Nov, 2015 2 commits
    • Andrii Grynenko's avatar
      Make collect work for types with no default constructors · 5bad4e9f
      Andrii Grynenko authored
      Summary: This doesn't make the code less efficient, because RVO can't be used for CollectVariadicContext. Thus moving existing tuple vs constructing new tuple by moving all values from other tuple (where each value is wrapped in folly::Optional) should be pretty much the same.
      
      Reviewed By: hannesr
      
      Differential Revision: D2650293
      
      fb-gh-sync-id: 648a358bf093a0bb9d058a997af9bf59014ad77c
      5bad4e9f
    • Yang Chi's avatar
      Allow a AsyncSocket to be corked the whole time · 07c15086
      Yang Chi authored
      Summary: Add a new method to cork a socket in a persistent manner, instead of the current on-off manner. This is default to false. The liger part of turning this on will be in a separate diff.
      
      I thought about whether I need to turn cork off based on some criteria to alleviate the perf degradation. The obvious things I can think off is just amount of data written as a threshold, or a timeout. But TCP is doing this already for us, unless we want the data threshold to be less than MSS, or we want the timeout to be less than 200ms. THoughts?
      
      Reviewed By: shikong
      
      Differential Revision: D2639260
      
      fb-gh-sync-id: 2821f669c9f72d5ac4c33195bb192fc4110ffe9d
      07c15086
  14. 12 Nov, 2015 3 commits
    • Giuseppe Ottaviano's avatar
      Make Malloc.h self-contained · 19d24e21
      Giuseppe Ottaviano authored
      Reviewed By: philippv
      
      Differential Revision: D2643313
      
      fb-gh-sync-id: 10b9f735725ce47fab4bbfaa5972b3863357365f
      19d24e21
    • Giuseppe Ottaviano's avatar
      Disable assertions in FBString when used as std::string · a348e154
      Giuseppe Ottaviano authored
      Reviewed By: Gownta
      
      Differential Revision: D2643850
      
      fb-gh-sync-id: 2c4bb844ea2006215b0637cb1ba08c636faefe05
      a348e154
    • Chad Parry's avatar
      Restore the definition of HHWheelTimer::UniquePtr · 65b8a020
      Chad Parry authored
      Summary: Changing the definition of `HHWheelTimer::UniquePtr` wasn't safe, because some clients were using that type outside of the `HHWheelTimer::newTimer` helper. I'm changing that part back. We'll still be able to proceed with my other codemod to `HHWheelTimer`, but we'll always have two different smart pointer types to manage: `UniquePtr` and `IntrusivePtr`.
      
      Reviewed By: djwatson
      
      Differential Revision: D2644721
      
      fb-gh-sync-id: 14685be62355f09d39c4139ef7186d60b5f48dcd
      65b8a020