passenger 3.0.21 → 3.9.1.beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data/DEVELOPERS.TXT +4 -10
- data/NEWS +19 -27
- data/Rakefile +20 -19
- data/bin/passenger +3 -2
- data/bin/passenger-config +35 -5
- data/bin/passenger-install-apache2-module +12 -12
- data/bin/passenger-install-nginx-module +55 -38
- data/bin/passenger-memory-stats +3 -1
- data/bin/passenger-status +7 -35
- data/build/agents.rb +107 -21
- data/build/apache2.rb +11 -46
- data/build/basics.rb +61 -9
- data/build/common_library.rb +59 -142
- data/build/cxx_tests.rb +111 -110
- data/build/documentation.rb +33 -0
- data/build/misc.rb +30 -12
- data/build/nginx.rb +10 -39
- data/build/oxt_tests.rb +1 -0
- data/build/ruby_extension.rb +1 -5
- data/build/test_basics.rb +3 -2
- data/dev/copy_boost_headers.rb +2 -1
- data/doc/Architectural overview.html +49 -90
- data/doc/DebuggingAndStressTesting.txt.md +49 -0
- data/doc/Packaging.txt.md +254 -0
- data/doc/Security of user switching support.html +35 -66
- data/doc/Users guide Apache.html +588 -758
- data/doc/Users guide Apache.idmap.txt +253 -136
- data/doc/Users guide Apache.txt +154 -109
- data/doc/Users guide Nginx.html +544 -660
- data/doc/Users guide Nginx.idmap.txt +179 -91
- data/doc/Users guide Nginx.txt +192 -118
- data/doc/Users guide Standalone.html +65 -48
- data/doc/Users guide Standalone.idmap.txt +10 -2
- data/doc/Users guide Standalone.txt +4 -0
- data/doc/images/glyphicons-halflings-white.png +0 -0
- data/doc/images/glyphicons-halflings.png +0 -0
- data/doc/images/phusion_banner_small.png +0 -0
- data/doc/images/{smart-lv2.png → smart.png} +0 -0
- data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
- data/doc/templates/bootstrap.min.css +397 -0
- data/doc/templates/markdown.html.erb +117 -0
- data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
- data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
- data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
- data/doc/users_guide_snippets/support_information.txt +30 -0
- data/ext/apache2/Bucket.cpp +9 -26
- data/ext/apache2/Bucket.h +13 -10
- data/ext/apache2/Configuration.cpp +70 -58
- data/ext/apache2/Configuration.hpp +19 -47
- data/ext/apache2/DirectoryMapper.h +7 -7
- data/ext/apache2/Hooks.cpp +150 -313
- data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
- data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
- data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
- data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
- data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
- data/ext/boost/algorithm/string/formatter.hpp +20 -3
- data/ext/boost/assert.hpp +85 -4
- data/ext/boost/bind/bind.hpp +1 -1
- data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
- data/ext/boost/concept_check.hpp +140 -64
- data/ext/boost/config.hpp +1 -1
- data/ext/boost/config/auto_link.hpp +8 -6
- data/ext/boost/config/compiler/borland.hpp +12 -2
- data/ext/boost/config/compiler/clang.hpp +89 -30
- data/ext/boost/config/compiler/codegear.hpp +3 -2
- data/ext/boost/config/compiler/common_edg.hpp +7 -5
- data/ext/boost/config/compiler/cray.hpp +61 -0
- data/ext/boost/config/compiler/digitalmars.hpp +9 -1
- data/ext/boost/config/compiler/gcc.hpp +33 -24
- data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
- data/ext/boost/config/compiler/hp_acc.hpp +12 -1
- data/ext/boost/config/compiler/intel.hpp +78 -4
- data/ext/boost/config/compiler/metrowerks.hpp +4 -1
- data/ext/boost/config/compiler/mpw.hpp +4 -1
- data/ext/boost/config/compiler/nvcc.hpp +8 -66
- data/ext/boost/config/compiler/pathscale.hpp +80 -0
- data/ext/boost/config/compiler/pgi.hpp +5 -5
- data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
- data/ext/boost/config/compiler/vacpp.hpp +37 -13
- data/ext/boost/config/compiler/visualc.hpp +24 -11
- data/ext/boost/config/platform/bsd.hpp +1 -1
- data/ext/boost/config/platform/cray.hpp +18 -0
- data/ext/boost/config/platform/cygwin.hpp +10 -0
- data/ext/boost/config/platform/linux.hpp +5 -0
- data/ext/boost/config/platform/macos.hpp +5 -4
- data/ext/boost/config/platform/symbian.hpp +5 -2
- data/ext/boost/config/platform/vms.hpp +25 -0
- data/ext/boost/config/platform/win32.hpp +7 -1
- data/ext/boost/config/select_compiler_config.hpp +8 -25
- data/ext/boost/config/select_platform_config.hpp +8 -1
- data/ext/boost/config/select_stdlib_config.hpp +9 -1
- data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
- data/ext/boost/config/stdlib/libcomo.hpp +1 -4
- data/ext/boost/config/stdlib/libcpp.hpp +36 -0
- data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
- data/ext/boost/config/stdlib/modena.hpp +1 -4
- data/ext/boost/config/stdlib/msl.hpp +1 -4
- data/ext/boost/config/stdlib/roguewave.hpp +9 -6
- data/ext/boost/config/stdlib/sgi.hpp +12 -4
- data/ext/boost/config/stdlib/stlport.hpp +11 -4
- data/ext/boost/config/stdlib/vacpp.hpp +11 -4
- data/ext/boost/config/suffix.hpp +71 -6
- data/ext/boost/config/warning_disable.hpp +1 -1
- data/ext/boost/container/container_fwd.hpp +177 -0
- data/ext/boost/cstdint.hpp +17 -12
- data/ext/boost/current_function.hpp +2 -1
- data/ext/boost/date_time/c_time.hpp +17 -1
- data/ext/boost/date_time/compiler_config.hpp +13 -15
- data/ext/boost/date_time/date_formatting.hpp +7 -1
- data/ext/boost/date_time/filetime_functions.hpp +4 -4
- data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
- data/ext/boost/date_time/strings_from_facet.hpp +3 -3
- data/ext/boost/date_time/time_facet.hpp +101 -101
- data/ext/boost/detail/endian.hpp +4 -2
- data/ext/boost/detail/fenv.hpp +74 -0
- data/ext/boost/detail/sp_typeinfo.hpp +6 -0
- data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
- data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
- data/ext/boost/exception/detail/type_info.hpp +3 -3
- data/ext/boost/exception/diagnostic_information.hpp +37 -21
- data/ext/boost/exception/exception.hpp +21 -1
- data/ext/boost/exception/info.hpp +0 -1
- data/ext/boost/function.hpp +2 -2
- data/ext/boost/function/function_base.hpp +15 -9
- data/ext/boost/function/function_template.hpp +26 -48
- data/ext/boost/integer_fwd.hpp +0 -16
- data/ext/boost/integer_traits.hpp +2 -2
- data/ext/boost/iterator.hpp +1 -1
- data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
- data/ext/boost/iterator/iterator_facade.hpp +13 -13
- data/ext/boost/iterator/transform_iterator.hpp +5 -20
- data/ext/boost/lexical_cast.hpp +1655 -673
- data/ext/boost/math/policies/policy.hpp +982 -0
- data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
- data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
- data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
- data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
- data/ext/boost/math/special_functions/sign.hpp +145 -0
- data/ext/boost/math/tools/config.hpp +321 -0
- data/ext/boost/math/tools/promotion.hpp +150 -0
- data/ext/boost/math/tools/real_cast.hpp +29 -0
- data/ext/boost/math/tools/user.hpp +97 -0
- data/ext/boost/move/move.hpp +1222 -0
- data/ext/boost/mpl/O1_size.hpp +40 -0
- data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
- data/ext/boost/mpl/advance.hpp +76 -0
- data/ext/boost/mpl/advance_fwd.hpp +28 -0
- data/ext/boost/mpl/at.hpp +52 -0
- data/ext/boost/mpl/at_fwd.hpp +24 -0
- data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
- data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
- data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
- data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
- data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
- data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
- data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
- data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
- data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
- data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
- data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
- data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
- data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
- data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
- data/ext/boost/mpl/aux_/has_size.hpp +23 -0
- data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
- data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
- data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
- data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
- data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
- data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
- data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
- data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
- data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
- data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
- data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
- data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
- data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
- data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
- data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
- data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
- data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
- data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
- data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
- data/ext/boost/mpl/back_fwd.hpp +24 -0
- data/ext/boost/mpl/back_inserter.hpp +34 -0
- data/ext/boost/mpl/begin_end.hpp +57 -0
- data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
- data/ext/boost/mpl/clear.hpp +39 -0
- data/ext/boost/mpl/clear_fwd.hpp +24 -0
- data/ext/boost/mpl/comparison.hpp +24 -0
- data/ext/boost/mpl/contains.hpp +41 -0
- data/ext/boost/mpl/contains_fwd.hpp +25 -0
- data/ext/boost/mpl/deref.hpp +41 -0
- data/ext/boost/mpl/distance.hpp +78 -0
- data/ext/boost/mpl/distance_fwd.hpp +28 -0
- data/ext/boost/mpl/empty_fwd.hpp +24 -0
- data/ext/boost/mpl/equal_to.hpp +21 -0
- data/ext/boost/mpl/find.hpp +38 -0
- data/ext/boost/mpl/find_if.hpp +50 -0
- data/ext/boost/mpl/fold.hpp +48 -0
- data/ext/boost/mpl/front_fwd.hpp +24 -0
- data/ext/boost/mpl/front_inserter.hpp +33 -0
- data/ext/boost/mpl/greater.hpp +21 -0
- data/ext/boost/mpl/greater_equal.hpp +21 -0
- data/ext/boost/mpl/inserter.hpp +32 -0
- data/ext/boost/mpl/iter_fold.hpp +49 -0
- data/ext/boost/mpl/iter_fold_if.hpp +117 -0
- data/ext/boost/mpl/iterator_range.hpp +42 -0
- data/ext/boost/mpl/iterator_tags.hpp +27 -0
- data/ext/boost/mpl/less.hpp +21 -0
- data/ext/boost/mpl/less_equal.hpp +21 -0
- data/ext/boost/mpl/limits/list.hpp +21 -0
- data/ext/boost/mpl/limits/vector.hpp +21 -0
- data/ext/boost/mpl/list.hpp +57 -0
- data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
- data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
- data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
- data/ext/boost/mpl/list/aux_/front.hpp +33 -0
- data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
- data/ext/boost/mpl/list/aux_/item.hpp +55 -0
- data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
- data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
- data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
- data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
- data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
- data/ext/boost/mpl/list/aux_/size.hpp +33 -0
- data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
- data/ext/boost/mpl/list/list0.hpp +42 -0
- data/ext/boost/mpl/list/list10.hpp +43 -0
- data/ext/boost/mpl/list/list20.hpp +43 -0
- data/ext/boost/mpl/long.hpp +22 -0
- data/ext/boost/mpl/long_fwd.hpp +27 -0
- data/ext/boost/mpl/minus.hpp +21 -0
- data/ext/boost/mpl/multiplies.hpp +53 -0
- data/ext/boost/mpl/negate.hpp +81 -0
- data/ext/boost/mpl/not_equal_to.hpp +21 -0
- data/ext/boost/mpl/numeric_cast.hpp +41 -0
- data/ext/boost/mpl/pair.hpp +70 -0
- data/ext/boost/mpl/plus.hpp +21 -0
- data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
- data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
- data/ext/boost/mpl/prior.hpp +19 -0
- data/ext/boost/mpl/push_back.hpp +53 -0
- data/ext/boost/mpl/push_back_fwd.hpp +24 -0
- data/ext/boost/mpl/push_front.hpp +52 -0
- data/ext/boost/mpl/push_front_fwd.hpp +24 -0
- data/ext/boost/mpl/remove_if.hpp +83 -0
- data/ext/boost/mpl/reverse_fold.hpp +50 -0
- data/ext/boost/mpl/same_as.hpp +55 -0
- data/ext/boost/mpl/sequence_tag.hpp +124 -0
- data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
- data/ext/boost/mpl/size.hpp +42 -0
- data/ext/boost/mpl/size_fwd.hpp +24 -0
- data/ext/boost/mpl/tag.hpp +52 -0
- data/ext/boost/mpl/times.hpp +21 -0
- data/ext/boost/mpl/vector.hpp +57 -0
- data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
- data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
- data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
- data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
- data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
- data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
- data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
- data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
- data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
- data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
- data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
- data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
- data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
- data/ext/boost/mpl/vector/vector0.hpp +34 -0
- data/ext/boost/mpl/vector/vector10.hpp +45 -0
- data/ext/boost/mpl/vector/vector20.hpp +45 -0
- data/ext/boost/none.hpp +1 -1
- data/ext/boost/numeric/conversion/bounds.hpp +24 -0
- data/ext/boost/numeric/conversion/cast.hpp +61 -0
- data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
- data/ext/boost/numeric/conversion/converter.hpp +68 -0
- data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
- data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
- data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
- data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
- data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
- data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
- data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
- data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
- data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
- data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
- data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
- data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
- data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
- data/ext/boost/operators.hpp +3 -1
- data/ext/boost/optional/optional.hpp +146 -79
- data/ext/boost/optional/optional_fwd.hpp +8 -1
- data/ext/boost/preprocessor/cat.hpp +2 -2
- data/ext/boost/preprocessor/config/config.hpp +39 -4
- data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
- data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
- data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
- data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
- data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
- data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
- data/ext/boost/preprocessor/seq/cat.hpp +5 -4
- data/ext/boost/preprocessor/seq/size.hpp +0 -1
- data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
- data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
- data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
- data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
- data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
- data/ext/boost/preprocessor/variadic/size.hpp +30 -0
- data/ext/boost/range/begin.hpp +17 -6
- data/ext/boost/range/concepts.hpp +37 -2
- data/ext/boost/range/detail/safe_bool.hpp +72 -0
- data/ext/boost/range/end.hpp +14 -9
- data/ext/boost/range/iterator_range_core.hpp +120 -12
- data/ext/boost/range/size.hpp +21 -5
- data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
- data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
- data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
- data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
- data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
- data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
- data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
- data/ext/boost/smart_ptr/make_shared.hpp +591 -22
- data/ext/boost/smart_ptr/shared_array.hpp +29 -1
- data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
- data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
- data/ext/boost/src/pthread/once.cpp +9 -7
- data/ext/boost/src/pthread/thread.cpp +32 -28
- data/ext/boost/src/pthread/timeconv.inl +4 -5
- data/ext/boost/src/tss_null.cpp +5 -1
- data/ext/boost/static_assert.hpp +8 -2
- data/ext/boost/thread/detail/config.hpp +19 -4
- data/ext/boost/thread/detail/move.hpp +11 -5
- data/ext/boost/thread/detail/thread.hpp +59 -43
- data/ext/boost/thread/exceptions.hpp +9 -9
- data/ext/boost/thread/future.hpp +150 -82
- data/ext/boost/thread/locks.hpp +101 -60
- data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
- data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
- data/ext/boost/thread/pthread/mutex.hpp +17 -14
- data/ext/boost/thread/pthread/once.hpp +3 -4
- data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
- data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
- data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
- data/ext/boost/thread/pthread/thread_data.hpp +40 -12
- data/ext/boost/thread/thread_time.hpp +5 -0
- data/ext/boost/throw_exception.hpp +1 -1
- data/ext/boost/token_functions.hpp +34 -10
- data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
- data/ext/boost/type_traits/alignment_of.hpp +1 -1
- data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
- data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
- data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
- data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
- data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
- data/ext/boost/type_traits/function_traits.hpp +1 -1
- data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
- data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
- data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
- data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
- data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
- data/ext/boost/type_traits/intrinsics.hpp +119 -71
- data/ext/boost/type_traits/is_const.hpp +5 -5
- data/ext/boost/type_traits/is_convertible.hpp +14 -13
- data/ext/boost/type_traits/is_enum.hpp +1 -1
- data/ext/boost/type_traits/is_floating_point.hpp +27 -0
- data/ext/boost/type_traits/is_function.hpp +3 -3
- data/ext/boost/type_traits/is_fundamental.hpp +1 -1
- data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_pod.hpp +11 -3
- data/ext/boost/type_traits/is_pointer.hpp +2 -2
- data/ext/boost/type_traits/is_signed.hpp +8 -3
- data/ext/boost/type_traits/is_union.hpp +8 -0
- data/ext/boost/type_traits/is_unsigned.hpp +9 -4
- data/ext/boost/type_traits/is_volatile.hpp +5 -5
- data/ext/boost/type_traits/remove_cv.hpp +4 -3
- data/ext/boost/type_traits/remove_pointer.hpp +51 -2
- data/ext/boost/type_traits/remove_reference.hpp +2 -2
- data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
- data/ext/boost/utility/declval.hpp +44 -0
- data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
- data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
- data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
- data/ext/boost/utility/in_place_factory.hpp +88 -0
- data/ext/boost/utility/result_of.hpp +103 -0
- data/ext/boost/utility/swap.hpp +55 -0
- data/ext/common/AnsiColorConstants.h +36 -0
- data/ext/common/ApplicationPool2/Common.h +87 -0
- data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
- data/ext/common/ApplicationPool2/Group.h +648 -0
- data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
- data/ext/common/ApplicationPool2/Options.h +576 -0
- data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
- data/ext/common/ApplicationPool2/Pool.h +1181 -0
- data/ext/common/ApplicationPool2/Process.h +425 -0
- data/ext/common/ApplicationPool2/README.md +96 -0
- data/ext/common/ApplicationPool2/Session.h +158 -0
- data/ext/common/ApplicationPool2/Socket.h +246 -0
- data/ext/common/ApplicationPool2/Spawner.h +2212 -0
- data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
- data/ext/common/BackgroundEventLoop.cpp +129 -0
- data/ext/common/BackgroundEventLoop.h +61 -0
- data/ext/common/Constants.h +3 -1
- data/ext/common/EventedBufferedInput.h +331 -0
- data/ext/common/EventedMessageServer.h +17 -34
- data/ext/common/EventedServer.h +2 -2
- data/ext/common/Exceptions.h +71 -19
- data/ext/common/FileDescriptor.h +8 -6
- data/ext/common/HttpConstants.h +167 -0
- data/ext/common/IniFile.h +24 -0
- data/ext/common/Logging.h +62 -849
- data/ext/common/MessageReadersWriters.h +19 -0
- data/ext/common/MessageServer.h +11 -14
- data/ext/common/MultiLibeio.cpp +198 -0
- data/ext/common/MultiLibeio.h +67 -0
- data/ext/common/ResourceLocator.h +24 -41
- data/ext/common/SafeLibev.h +186 -14
- data/ext/common/StaticString.h +23 -3
- data/ext/common/UnionStation.h +972 -0
- data/ext/common/Utils.cpp +168 -24
- data/ext/common/Utils.h +25 -3
- data/ext/common/Utils/CachedFileStat.hpp +4 -3
- data/ext/common/Utils/FileChangeChecker.h +2 -2
- data/ext/common/Utils/HashMap.h +50 -0
- data/ext/common/Utils/IOUtils.cpp +229 -68
- data/ext/common/Utils/IOUtils.h +134 -3
- data/ext/common/Utils/Lock.h +28 -0
- data/ext/common/Utils/MemoryBarrier.h +52 -0
- data/ext/common/Utils/PriorityQueue.h +54 -0
- data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
- data/ext/common/Utils/ScopeGuard.h +50 -1
- data/ext/common/Utils/SmallVector.h +653 -0
- data/ext/common/Utils/StrIntUtils.cpp +26 -2
- data/ext/common/Utils/StrIntUtils.h +18 -2
- data/ext/common/Utils/StringMap.h +125 -8
- data/ext/common/Utils/Template.h +212 -0
- data/ext/common/Utils/fib.c +699 -0
- data/ext/common/Utils/fib.h +101 -0
- data/ext/common/Utils/fibpriv.h +67 -0
- data/ext/common/Utils/json-forwards.h +249 -0
- data/ext/common/Utils/json.h +1855 -0
- data/ext/common/Utils/jsoncpp.cpp +4230 -0
- data/ext/common/agents/Base.cpp +1126 -0
- data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
- data/ext/common/agents/EnvPrinter.c +16 -0
- data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
- data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
- data/ext/common/agents/HelperAgent/Main.cpp +497 -0
- data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
- data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
- data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
- data/ext/common/agents/SpawnPreparer.cpp +127 -0
- data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
- data/ext/libeio/Changes +72 -0
- data/ext/{google/COPYING → libeio/LICENSE} +17 -9
- data/ext/libeio/Makefile.am +15 -0
- data/ext/libeio/Makefile.in +694 -0
- data/ext/libeio/aclocal.m4 +9418 -0
- data/ext/libeio/autogen.sh +3 -0
- data/ext/libeio/config.guess +1501 -0
- data/ext/libeio/config.h.in +136 -0
- data/ext/libeio/config.sub +1705 -0
- data/ext/libeio/configure +14822 -0
- data/ext/libeio/configure.ac +22 -0
- data/ext/libeio/demo.c +194 -0
- data/ext/libeio/ecb.h +457 -0
- data/ext/libeio/eio.c +2816 -0
- data/ext/libeio/eio.h +411 -0
- data/ext/libeio/install-sh +520 -0
- data/ext/libeio/libeio.m4 +211 -0
- data/ext/libeio/ltmain.sh +9636 -0
- data/ext/libeio/missing +376 -0
- data/ext/libeio/xthread.h +166 -0
- data/ext/libev/Changes +125 -7
- data/ext/libev/Makefile.am +5 -3
- data/ext/libev/Makefile.in +209 -120
- data/ext/libev/aclocal.m4 +6027 -4619
- data/ext/libev/autogen.sh +1 -4
- data/ext/libev/config.h.in +11 -7
- data/ext/libev/configure +7312 -14993
- data/ext/libev/configure.ac +12 -5
- data/ext/libev/depcomp +630 -0
- data/ext/libev/ev++.h +48 -32
- data/ext/libev/ev.c +1173 -391
- data/ext/libev/ev.h +315 -181
- data/ext/libev/ev_epoll.c +66 -15
- data/ext/libev/ev_kqueue.c +20 -18
- data/ext/libev/ev_poll.c +27 -23
- data/ext/libev/ev_port.c +39 -19
- data/ext/libev/ev_select.c +23 -17
- data/ext/libev/ev_vars.h +25 -8
- data/ext/libev/ev_win32.c +6 -6
- data/ext/libev/ev_wrap.h +22 -2
- data/ext/libev/event.c +18 -17
- data/ext/libev/event.h +16 -4
- data/ext/libev/libev.m4 +10 -6
- data/ext/libev/ltmain.sh +7353 -5811
- data/ext/nginx/Configuration.c +74 -42
- data/ext/nginx/Configuration.h +3 -5
- data/ext/nginx/ContentHandler.c +26 -83
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +13 -9
- data/ext/nginx/ngx_http_passenger_module.c +3 -7
- data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
- data/ext/oxt/detail/context.hpp +90 -0
- data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
- data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
- data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
- data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
- data/ext/oxt/dynamic_thread_group.hpp +27 -1
- data/ext/oxt/implementation.cpp +415 -0
- data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
- data/ext/oxt/macros.hpp +32 -1
- data/ext/oxt/spin_lock.hpp +6 -11
- data/ext/oxt/system_calls.cpp +204 -16
- data/ext/oxt/system_calls.hpp +85 -45
- data/ext/oxt/thread.hpp +13 -117
- data/ext/ruby/passenger_native_support.c +82 -237
- data/helper-scripts/backtrace-sanitizer.rb +114 -0
- data/helper-scripts/classic-rails-loader.rb +135 -0
- data/helper-scripts/classic-rails-preloader.rb +161 -0
- data/helper-scripts/node-loader.js +314 -0
- data/helper-scripts/rack-loader.rb +104 -0
- data/helper-scripts/rack-preloader.rb +132 -0
- data/helper-scripts/wsgi-loader.py +231 -0
- data/helper-scripts/wsgi-preloader.py +1 -0
- data/lib/phusion_passenger.rb +159 -61
- data/lib/phusion_passenger/abstract_installer.rb +182 -87
- data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
- data/lib/phusion_passenger/analytics_logger.rb +5 -4
- data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
- data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
- data/lib/phusion_passenger/common_library.rb +441 -0
- data/lib/phusion_passenger/console_text_template.rb +4 -16
- data/lib/phusion_passenger/constants.rb +1 -8
- data/lib/phusion_passenger/debug_logging.rb +5 -2
- data/lib/phusion_passenger/dependencies.rb +51 -13
- data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
- data/lib/phusion_passenger/message_channel.rb +3 -47
- data/lib/phusion_passenger/message_client.rb +2 -2
- data/lib/phusion_passenger/native_support.rb +36 -15
- data/lib/phusion_passenger/packaging.rb +8 -11
- data/lib/phusion_passenger/platform_info.rb +25 -17
- data/lib/phusion_passenger/platform_info/apache.rb +10 -7
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
- data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
- data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
- data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
- data/lib/phusion_passenger/public_api.rb +1 -4
- data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
- data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
- data/lib/phusion_passenger/request_handler.rb +500 -0
- data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
- data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
- data/lib/phusion_passenger/standalone/command.rb +36 -15
- data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
- data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
- data/lib/phusion_passenger/standalone/start_command.rb +44 -39
- data/lib/phusion_passenger/standalone/utils.rb +5 -5
- data/lib/phusion_passenger/utils.rb +35 -914
- data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
- data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
- data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
- data/lib/phusion_passenger/utils/tee_input.rb +174 -0
- data/lib/phusion_passenger/utils/tmpio.rb +33 -0
- data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
- data/resources/mime.types +5 -1
- data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
- data/resources/templates/error_layout.html.template +89 -0
- data/resources/templates/general_error.html.template +1 -0
- data/resources/templates/general_error_with_html.html.template +1 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
- data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
- data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
- data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
- data/resources/templates/undisclosed_error.html.template +25 -0
- data/test/config.json.example +42 -0
- data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
- data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
- data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
- data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
- data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
- data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
- data/test/cxx/BufferedIOTest.cpp +7 -7
- data/test/cxx/CxxTestMain.cpp +65 -2
- data/test/cxx/FileBackedPipeTest.cpp +626 -0
- data/test/cxx/FileChangeCheckerTest.cpp +20 -18
- data/test/cxx/FilterSupportTest.cpp +5 -5
- data/test/cxx/IOUtilsTest.cpp +11 -4
- data/test/cxx/MessageReadersWritersTest.cpp +1 -1
- data/test/cxx/MessageServerTest.cpp +31 -30
- data/test/cxx/RequestHandlerTest.cpp +777 -0
- data/test/cxx/ScgiRequestParserTest.cpp +36 -16
- data/test/cxx/ServerInstanceDirTest.cpp +1 -1
- data/test/cxx/StringMapTest.cpp +61 -0
- data/test/cxx/TemplateTest.cpp +118 -0
- data/test/cxx/TestSupport.cpp +25 -68
- data/test/cxx/TestSupport.h +81 -41
- data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
- data/test/cxx/UtilsTest.cpp +59 -5
- data/test/integration_tests/apache2_tests.rb +2 -2
- data/test/integration_tests/nginx_tests.rb +1 -1
- data/test/integration_tests/spec_helper.rb +7 -5
- data/test/oxt/oxt_test_main.cpp +2 -0
- data/test/oxt/syscall_interruption_test.cpp +1 -0
- data/test/ruby/classic_rails/loader_spec.rb +48 -0
- data/test/ruby/classic_rails/preloader_spec.rb +54 -0
- data/test/ruby/rack/loader_spec.rb +62 -0
- data/test/ruby/rack/preloader_spec.rb +74 -0
- data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
- data/test/ruby/shared/loader_spec.rb +241 -0
- data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
- data/test/ruby/shared/ruby_loader_spec.rb +55 -0
- data/test/ruby/spec_helper.rb +8 -53
- data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
- data/test/ruby/utils_spec.rb +10 -683
- data/test/stub/rack/config.ru +28 -3
- data/test/stub/rack/start.rb +47 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
- data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
- data/test/stub/rails3.0/Gemfile.lock +80 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
- data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
- data/test/stub/start_error.pl +24 -0
- data/test/stub/wsgi/passenger_wsgi.py +71 -3
- data/test/support/apache2_controller.rb +2 -2
- data/test/support/placebo-preloader.rb +88 -0
- data/test/support/test_helper.rb +1 -14
- data/test/tut/tut.h +11 -4
- metadata +590 -326
- data.tar.gz.asc +0 -12
- data/PACKAGING.TXT +0 -25
- data/build/config.rb +0 -46
- data/ext/apache2/HelperAgent.cpp +0 -364
- data/ext/boost/call_traits.hpp +0 -24
- data/ext/boost/detail/call_traits.hpp +0 -164
- data/ext/common/AbstractSpawnManager.h +0 -110
- data/ext/common/AgentBase.cpp +0 -432
- data/ext/common/ApplicationPool/Client.h +0 -788
- data/ext/common/ApplicationPool/Interface.h +0 -295
- data/ext/common/ApplicationPool/Pool.h +0 -1327
- data/ext/common/ApplicationPool/Server.h +0 -479
- data/ext/common/MessageChannel.h +0 -494
- data/ext/common/PoolOptions.h +0 -518
- data/ext/common/Process.h +0 -253
- data/ext/common/Session.h +0 -436
- data/ext/common/SpawnManager.h +0 -611
- data/ext/google/ChangeLog +0 -167
- data/ext/google/dense_hash_map +0 -310
- data/ext/google/dense_hash_set +0 -287
- data/ext/google/sparse_hash_map +0 -294
- data/ext/google/sparse_hash_set +0 -275
- data/ext/google/sparsehash/densehashtable.h +0 -1062
- data/ext/google/sparsehash/sparseconfig.h +0 -55
- data/ext/google/sparsehash/sparsehashtable.h +0 -1015
- data/ext/google/sparsetable +0 -1468
- data/ext/google/type_traits.h +0 -250
- data/ext/nginx/HelperAgent.cpp +0 -1355
- data/ext/nginx/ScgiRequestParser.h +0 -375
- data/ext/oxt/backtrace.cpp +0 -185
- data/ext/oxt/tracable_exception.cpp +0 -89
- data/helper-scripts/passenger-spawn-server +0 -106
- data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
- data/lib/phusion_passenger/abstract_server.rb +0 -372
- data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
- data/lib/phusion_passenger/app_process.rb +0 -174
- data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
- data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
- data/lib/phusion_passenger/exceptions.rb +0 -103
- data/lib/phusion_passenger/html_template.rb +0 -107
- data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
- data/lib/phusion_passenger/spawn_manager.rb +0 -359
- data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
- data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
- data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
- data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
- data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
- data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
- data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
- data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
- data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
- data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
- data/test/config.yml.example +0 -41
- data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
- data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
- data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
- data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
- data/test/cxx/MessageChannelTest.cpp +0 -557
- data/test/cxx/PoolOptionsTest.cpp +0 -116
- data/test/cxx/SpawnManagerTest.cpp +0 -161
- data/test/ruby/abstract_server_collection_spec.rb +0 -247
- data/test/ruby/abstract_server_spec.rb +0 -61
- data/test/ruby/app_process_spec.rb +0 -43
- data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
- data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
- data/test/ruby/rack/application_spawner_spec.rb +0 -116
- data/test/ruby/shared/abstract_server_spec.rb +0 -23
- data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
- data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
- data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
- data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
- data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
- data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
- data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
- data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
- data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
- data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
- data/test/ruby/spawn_manager_spec.rb +0 -134
- data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
- data/test/stub/message_channel.rb +0 -11
- data/test/stub/message_channel_2.rb +0 -12
- data/test/stub/message_channel_3.rb +0 -19
- data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
- data/test/stub/spawn_server.rb +0 -22
- metadata.gz.asc +0 -12
@@ -0,0 +1,61 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - http://www.modrails.com/
|
3
|
+
* Copyright (c) 2012 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#ifndef _PASSENGER_APPLICATION_POOL_PIPE_WATCHER_H_
|
26
|
+
#define _PASSENGER_APPLICATION_POOL_PIPE_WATCHER_H_
|
27
|
+
|
28
|
+
#include <boost/shared_ptr.hpp>
|
29
|
+
#include <boost/enable_shared_from_this.hpp>
|
30
|
+
#include <SafeLibev.h>
|
31
|
+
#include <FileDescriptor.h>
|
32
|
+
#include <ev++.h>
|
33
|
+
|
34
|
+
namespace Passenger {
|
35
|
+
namespace ApplicationPool2 {
|
36
|
+
|
37
|
+
using namespace boost;
|
38
|
+
|
39
|
+
|
40
|
+
struct PipeWatcher: public enable_shared_from_this<PipeWatcher> {
|
41
|
+
SafeLibevPtr libev;
|
42
|
+
FileDescriptor fd;
|
43
|
+
ev::io watcher;
|
44
|
+
shared_ptr<PipeWatcher> selfPointer;
|
45
|
+
int fdToForwardTo;
|
46
|
+
|
47
|
+
PipeWatcher(const SafeLibevPtr &_libev,
|
48
|
+
const FileDescriptor &_fd,
|
49
|
+
int _fdToForwardTo);
|
50
|
+
~PipeWatcher();
|
51
|
+
void start();
|
52
|
+
void onReadable(ev::io &io, int revents);
|
53
|
+
};
|
54
|
+
|
55
|
+
typedef shared_ptr<PipeWatcher> PipeWatcherPtr;
|
56
|
+
|
57
|
+
|
58
|
+
} // namespace ApplicationPool2
|
59
|
+
} // namespace Passenger
|
60
|
+
|
61
|
+
#endif /* _PASSENGER_APPLICATION_POOL_PIPE_WATCHER_H_ */
|
@@ -0,0 +1,1181 @@
|
|
1
|
+
/*
|
2
|
+
* Phusion Passenger - http://www.modrails.com/
|
3
|
+
* Copyright (c) 2011, 2012 Phusion
|
4
|
+
*
|
5
|
+
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
|
+
*
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
12
|
+
* furnished to do so, subject to the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
15
|
+
* all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
* THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
#ifndef _PASSENGER_APPLICATION_POOL2_POOL_H_
|
26
|
+
#define _PASSENGER_APPLICATION_POOL2_POOL_H_
|
27
|
+
|
28
|
+
#include <string>
|
29
|
+
#include <vector>
|
30
|
+
#include <utility>
|
31
|
+
#include <sstream>
|
32
|
+
#include <iomanip>
|
33
|
+
#include <boost/thread.hpp>
|
34
|
+
#include <boost/bind.hpp>
|
35
|
+
#include <boost/shared_ptr.hpp>
|
36
|
+
#include <boost/make_shared.hpp>
|
37
|
+
#include <boost/function.hpp>
|
38
|
+
#include <oxt/dynamic_thread_group.hpp>
|
39
|
+
#include <oxt/backtrace.hpp>
|
40
|
+
#include <ApplicationPool2/Common.h>
|
41
|
+
#include <ApplicationPool2/Process.h>
|
42
|
+
#include <ApplicationPool2/Group.h>
|
43
|
+
#include <ApplicationPool2/SuperGroup.h>
|
44
|
+
#include <ApplicationPool2/Session.h>
|
45
|
+
#include <ApplicationPool2/Spawner.h>
|
46
|
+
#include <ApplicationPool2/Options.h>
|
47
|
+
#include <UnionStation.h>
|
48
|
+
#include <Logging.h>
|
49
|
+
#include <SafeLibev.h>
|
50
|
+
#include <AnsiColorConstants.h>
|
51
|
+
#include <Exceptions.h>
|
52
|
+
#include <RandomGenerator.h>
|
53
|
+
#include <Utils/Lock.h>
|
54
|
+
#include <Utils/SystemTime.h>
|
55
|
+
#include <Utils/VariantMap.h>
|
56
|
+
#include <Utils/ProcessMetricsCollector.h>
|
57
|
+
|
58
|
+
namespace Passenger {
|
59
|
+
namespace ApplicationPool2 {
|
60
|
+
|
61
|
+
using namespace std;
|
62
|
+
using namespace boost;
|
63
|
+
using namespace oxt;
|
64
|
+
|
65
|
+
|
66
|
+
class Pool: public enable_shared_from_this<Pool> {
|
67
|
+
public:
|
68
|
+
struct InspectOptions {
|
69
|
+
bool colorize;
|
70
|
+
bool verbose;
|
71
|
+
|
72
|
+
InspectOptions()
|
73
|
+
: colorize(false),
|
74
|
+
verbose(false)
|
75
|
+
{ }
|
76
|
+
|
77
|
+
InspectOptions(const VariantMap &options)
|
78
|
+
: colorize(options.getBool("colorize", false, false)),
|
79
|
+
verbose(options.getBool("verbose", false, false))
|
80
|
+
{ }
|
81
|
+
};
|
82
|
+
|
83
|
+
// Actually private, but marked public so that unit tests can access the fields.
|
84
|
+
public:
|
85
|
+
friend class SuperGroup;
|
86
|
+
friend class Group;
|
87
|
+
typedef UnionStation::LoggerFactory LoggerFactory;
|
88
|
+
typedef UnionStation::LoggerFactoryPtr LoggerFactoryPtr;
|
89
|
+
typedef UnionStation::LoggerPtr LoggerPtr;
|
90
|
+
|
91
|
+
SpawnerFactoryPtr spawnerFactory;
|
92
|
+
LoggerFactoryPtr loggerFactory;
|
93
|
+
RandomGeneratorPtr randomGenerator;
|
94
|
+
|
95
|
+
mutable boost::mutex syncher;
|
96
|
+
SafeLibev *libev;
|
97
|
+
unsigned int max;
|
98
|
+
unsigned long long maxIdleTime;
|
99
|
+
|
100
|
+
ev::timer garbageCollectionTimer;
|
101
|
+
ev::timer analyticsCollectionTimer;
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Code can register background threads in one of these dynamic thread groups
|
105
|
+
* to ensure that threads are interrupted and/or joined properly upon Pool
|
106
|
+
* destruction.
|
107
|
+
* All threads in 'interruptableThreads' will be interrupted and joined upon
|
108
|
+
* Pool destruction.
|
109
|
+
* All threads in 'nonInterruptableThreads' will be joined, but not interrupted,
|
110
|
+
* upon Pool destruction.
|
111
|
+
*/
|
112
|
+
dynamic_thread_group interruptableThreads;
|
113
|
+
dynamic_thread_group nonInterruptableThreads;
|
114
|
+
|
115
|
+
SuperGroupMap superGroups;
|
116
|
+
|
117
|
+
/**
|
118
|
+
* get() requests that...
|
119
|
+
* - cannot be immediately satisfied because the pool is at full
|
120
|
+
* capacity and no existing processes can be killed,
|
121
|
+
* - and for which the super group isn't in the pool,
|
122
|
+
* ...are put on this wait list.
|
123
|
+
*
|
124
|
+
* This wait list is processed when one of the following things happen:
|
125
|
+
*
|
126
|
+
* - A process has been spawned but its associated group has
|
127
|
+
* no get waiters. This process can be killed and the resulting
|
128
|
+
* free capacity will be used to use spawn a process for this
|
129
|
+
* get request.
|
130
|
+
* - A process (that has apparently been spawned after getWaitlist
|
131
|
+
* was populated) is done processing a request. This process can
|
132
|
+
* then be killed to free capacity.
|
133
|
+
* - A process has failed to spawn, resulting in capacity to
|
134
|
+
* become free.
|
135
|
+
* - A SuperGroup failed to initialize, resulting in free capacity.
|
136
|
+
* - Someone commanded Pool to detach a process, resulting in free
|
137
|
+
* capacity.
|
138
|
+
* - Someone commanded Pool to detach a SuperGroup, resulting in
|
139
|
+
* free capacity.
|
140
|
+
* - The 'max' option has been increased, resulting in free capacity.
|
141
|
+
*
|
142
|
+
* Invariant 1:
|
143
|
+
* for all options in getWaitlist:
|
144
|
+
* options.getAppGroupName() is not in 'superGroups'.
|
145
|
+
*
|
146
|
+
* Invariant 2:
|
147
|
+
* if getWaitlist is non-empty:
|
148
|
+
* atFullCapacity()
|
149
|
+
* Equivalently:
|
150
|
+
* if !atFullCapacity():
|
151
|
+
* getWaitlist is empty.
|
152
|
+
*/
|
153
|
+
vector<GetWaiter> getWaitlist;
|
154
|
+
|
155
|
+
mutable boost::mutex debugSyncher;
|
156
|
+
unsigned short spawnLoopIteration;
|
157
|
+
|
158
|
+
static void runAllActions(const vector<Callback> &actions) {
|
159
|
+
vector<Callback>::const_iterator it, end = actions.end();
|
160
|
+
for (it = actions.begin(); it != end; it++) {
|
161
|
+
(*it)();
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
static void runAllActionsWithCopy(vector<Callback> actions) {
|
166
|
+
runAllActions(actions);
|
167
|
+
}
|
168
|
+
|
169
|
+
static const char *maybeColorize(const InspectOptions &options, const char *color) {
|
170
|
+
if (options.colorize) {
|
171
|
+
return color;
|
172
|
+
} else {
|
173
|
+
return "";
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
void verifyInvariants() const {
|
178
|
+
// !a || b: logical equivalent of a IMPLIES b.
|
179
|
+
P_ASSERT(!( !getWaitlist.empty() ) || ( atFullCapacity(false) ));
|
180
|
+
P_ASSERT(!( !atFullCapacity(false) ) || ( getWaitlist.empty() ));
|
181
|
+
}
|
182
|
+
|
183
|
+
void verifyExpensiveInvariants() const {
|
184
|
+
#ifndef NDEBUG
|
185
|
+
vector<GetWaiter>::const_iterator it, end = getWaitlist.end();
|
186
|
+
for (it = getWaitlist.begin(); it != end; it++) {
|
187
|
+
const GetWaiter &waiter = *it;
|
188
|
+
P_ASSERT(superGroups.get(waiter.options.getAppGroupName()) == NULL);
|
189
|
+
}
|
190
|
+
#endif
|
191
|
+
}
|
192
|
+
|
193
|
+
ProcessPtr findOldestIdleProcess() const {
|
194
|
+
ProcessPtr oldestIdleProcess;
|
195
|
+
|
196
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
197
|
+
for (it = superGroups.begin(); it != end; it++) {
|
198
|
+
const SuperGroupPtr &superGroup = it->second;
|
199
|
+
const vector<GroupPtr> &groups = superGroup->groups;
|
200
|
+
vector<GroupPtr>::const_iterator g_it, g_end = groups.end();
|
201
|
+
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
202
|
+
const GroupPtr &group = *g_it;
|
203
|
+
const ProcessList &processes = group->processes;
|
204
|
+
ProcessList::const_iterator p_it, p_end = processes.end();
|
205
|
+
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
206
|
+
const ProcessPtr process = *p_it;
|
207
|
+
if (process->utilization() == 0
|
208
|
+
&& (oldestIdleProcess == NULL
|
209
|
+
|| process->lastUsed < oldestIdleProcess->lastUsed)
|
210
|
+
) {
|
211
|
+
oldestIdleProcess = process;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
return oldestIdleProcess;
|
218
|
+
}
|
219
|
+
|
220
|
+
ProcessPtr findBestProcessToTrash() const {
|
221
|
+
ProcessPtr oldestProcess;
|
222
|
+
|
223
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
224
|
+
for (it = superGroups.begin(); it != end; it++) {
|
225
|
+
const SuperGroupPtr &superGroup = it->second;
|
226
|
+
const vector<GroupPtr> &groups = superGroup->groups;
|
227
|
+
vector<GroupPtr>::const_iterator g_it, g_end = groups.end();
|
228
|
+
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
229
|
+
const GroupPtr &group = *g_it;
|
230
|
+
const ProcessList &processes = group->processes;
|
231
|
+
ProcessList::const_iterator p_it, p_end = processes.end();
|
232
|
+
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
233
|
+
const ProcessPtr process = *p_it;
|
234
|
+
if (oldestProcess == NULL
|
235
|
+
|| process->lastUsed < oldestProcess->lastUsed) {
|
236
|
+
oldestProcess = process;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
return oldestProcess;
|
243
|
+
}
|
244
|
+
|
245
|
+
/** Process all waiters on the getWaitlist. Call when capacity has become free.
|
246
|
+
* This function assigns sessions to them by calling get() on the corresponding
|
247
|
+
* SuperGroups, or by creating more SuperGroups, in so far the new capacity allows.
|
248
|
+
*/
|
249
|
+
void assignSessionsToGetWaiters(vector<Callback> &postLockActions) {
|
250
|
+
bool done = false;
|
251
|
+
vector<GetWaiter>::iterator it, end = getWaitlist.end();
|
252
|
+
vector<GetWaiter> newWaitlist;
|
253
|
+
|
254
|
+
for (it = getWaitlist.begin(); it != end && !done; it++) {
|
255
|
+
GetWaiter &waiter = *it;
|
256
|
+
|
257
|
+
SuperGroup *superGroup = findMatchingSuperGroup(waiter.options);
|
258
|
+
if (superGroup != NULL) {
|
259
|
+
SessionPtr session = superGroup->get(waiter.options, waiter.callback);
|
260
|
+
if (session != NULL) {
|
261
|
+
postLockActions.push_back(boost::bind(
|
262
|
+
waiter.callback, session, ExceptionPtr()));
|
263
|
+
}
|
264
|
+
/* else: the callback has now been put in
|
265
|
+
* the group's get wait list.
|
266
|
+
*/
|
267
|
+
} else if (!atFullCapacity(false)) {
|
268
|
+
createSuperGroupAndAsyncGetFromIt(waiter.options, waiter.callback);
|
269
|
+
} else {
|
270
|
+
/* Still cannot satisfy this get request. Keep it on the get
|
271
|
+
* wait list and try again later.
|
272
|
+
*/
|
273
|
+
newWaitlist.push_back(waiter);
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
getWaitlist = newWaitlist;
|
278
|
+
}
|
279
|
+
|
280
|
+
void possiblySpawnMoreProcessesForExistingGroups() {
|
281
|
+
SuperGroupMap::iterator it, end = superGroups.end();
|
282
|
+
for (it = superGroups.begin(); it != end; it++) {
|
283
|
+
SuperGroupPtr &superGroup = it->second;
|
284
|
+
vector<GroupPtr> &groups = superGroup->groups;
|
285
|
+
vector<GroupPtr>::iterator g_it, g_end = groups.end();
|
286
|
+
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
287
|
+
GroupPtr &group = *g_it;
|
288
|
+
if (!group->getWaitlist.empty() && group->shouldSpawn()) {
|
289
|
+
group->spawn();
|
290
|
+
}
|
291
|
+
group->verifyInvariants();
|
292
|
+
}
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
void migrateGroupGetWaitlistToPool(const GroupPtr &group) {
|
297
|
+
getWaitlist.reserve(getWaitlist.size() + group->getWaitlist.size());
|
298
|
+
while (!group->getWaitlist.empty()) {
|
299
|
+
getWaitlist.push_back(group->getWaitlist.front());
|
300
|
+
group->getWaitlist.pop();
|
301
|
+
}
|
302
|
+
}
|
303
|
+
|
304
|
+
void migrateSuperGroupGetWaitlistToPool(const SuperGroupPtr &superGroup) {
|
305
|
+
getWaitlist.reserve(getWaitlist.size() + superGroup->getWaitlist.size());
|
306
|
+
while (!superGroup->getWaitlist.empty()) {
|
307
|
+
getWaitlist.push_back(superGroup->getWaitlist.front());
|
308
|
+
superGroup->getWaitlist.pop();
|
309
|
+
}
|
310
|
+
}
|
311
|
+
|
312
|
+
/**
|
313
|
+
* Forcefully destroys and detaches the given SuperGroup. After detaching
|
314
|
+
* the SuperGroup may have a non-empty getWaitlist so be sure to do
|
315
|
+
* something with it.
|
316
|
+
*
|
317
|
+
* 'superGroup' is a non-const non-reference smart pointer so that
|
318
|
+
* it does not get destroy immediately after the 'superGroups.remove()'
|
319
|
+
* call.
|
320
|
+
*/
|
321
|
+
void forceDetachSuperGroup(SuperGroupPtr superGroup, vector<Callback> &postLockActions) {
|
322
|
+
bool removed = superGroups.remove(superGroup->name);
|
323
|
+
P_ASSERT(removed);
|
324
|
+
(void) removed; // Shut up compiler warning.
|
325
|
+
superGroup->destroy(postLockActions, false);
|
326
|
+
superGroup->setPool(PoolPtr());
|
327
|
+
}
|
328
|
+
|
329
|
+
bool detachProcessUnlocked(const ProcessPtr &process, vector<Callback> &postLockActions) {
|
330
|
+
GroupPtr group = process->getGroup();
|
331
|
+
if (group != NULL && group->getPool().get() == this) {
|
332
|
+
verifyInvariants();
|
333
|
+
|
334
|
+
SuperGroupPtr superGroup = group->getSuperGroup();
|
335
|
+
P_ASSERT(superGroup->state != SuperGroup::INITIALIZING);
|
336
|
+
P_ASSERT(superGroup->getWaitlist.empty());
|
337
|
+
|
338
|
+
group->detach(process, postLockActions);
|
339
|
+
if (group->processes.empty()
|
340
|
+
&& !group->spawning()
|
341
|
+
&& !group->getWaitlist.empty()) {
|
342
|
+
migrateGroupGetWaitlistToPool(group);
|
343
|
+
}
|
344
|
+
group->verifyInvariants();
|
345
|
+
superGroup->verifyInvariants();
|
346
|
+
|
347
|
+
assignSessionsToGetWaiters(postLockActions);
|
348
|
+
|
349
|
+
if (superGroup->garbageCollectable()) {
|
350
|
+
// possiblySpawnMoreProcessesForExistingGroups()
|
351
|
+
// already called via detachSuperGroup().
|
352
|
+
detachSuperGroup(superGroup, false, &postLockActions);
|
353
|
+
} else {
|
354
|
+
possiblySpawnMoreProcessesForExistingGroups();
|
355
|
+
}
|
356
|
+
|
357
|
+
verifyInvariants();
|
358
|
+
verifyExpensiveInvariants();
|
359
|
+
|
360
|
+
return true;
|
361
|
+
} else {
|
362
|
+
return false;
|
363
|
+
}
|
364
|
+
}
|
365
|
+
|
366
|
+
static void syncGetCallback(Ticket *ticket, const SessionPtr &session, const ExceptionPtr &e) {
|
367
|
+
ScopedLock lock(ticket->syncher);
|
368
|
+
if (OXT_LIKELY(session != NULL)) {
|
369
|
+
ticket->session = session;
|
370
|
+
} else {
|
371
|
+
ticket->exception = e;
|
372
|
+
}
|
373
|
+
ticket->cond.notify_one();
|
374
|
+
}
|
375
|
+
|
376
|
+
SuperGroup *findMatchingSuperGroup(const Options &options) {
|
377
|
+
return superGroups.get(options.getAppGroupName()).get();
|
378
|
+
}
|
379
|
+
|
380
|
+
void garbageCollect(ev::timer &timer, int revents) {
|
381
|
+
PoolPtr self = shared_from_this(); // Keep pool object alive.
|
382
|
+
TRACE_POINT();
|
383
|
+
ScopedLock lock(syncher);
|
384
|
+
SuperGroupMap::iterator it, end = superGroups.end();
|
385
|
+
vector<SuperGroupPtr> superGroupsToDetach;
|
386
|
+
vector<Callback> actions;
|
387
|
+
unsigned long long now = SystemTime::getUsec();
|
388
|
+
unsigned long long nextGcRunTime = 0;
|
389
|
+
|
390
|
+
P_DEBUG("Garbage collection time");
|
391
|
+
verifyInvariants();
|
392
|
+
|
393
|
+
// For all supergroups and groups...
|
394
|
+
for (it = superGroups.begin(); it != end; it++) {
|
395
|
+
SuperGroupPtr superGroup = it->second;
|
396
|
+
vector<GroupPtr> &groups = superGroup->groups;
|
397
|
+
vector<GroupPtr>::iterator g_it, g_end = groups.end();
|
398
|
+
|
399
|
+
superGroup->verifyInvariants();
|
400
|
+
|
401
|
+
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
402
|
+
GroupPtr group = *g_it;
|
403
|
+
ProcessList &processes = group->processes;
|
404
|
+
ProcessList::iterator p_it, p_end = processes.end();
|
405
|
+
|
406
|
+
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
407
|
+
ProcessPtr process = *p_it;
|
408
|
+
|
409
|
+
// ...detach processes that have been idle for more than maxIdleTime.
|
410
|
+
unsigned long long processGcTime =
|
411
|
+
process->lastUsed + maxIdleTime;
|
412
|
+
if (process->sessions == 0
|
413
|
+
&& now >= processGcTime
|
414
|
+
&& (unsigned long) group->count > group->options.minProcesses) {
|
415
|
+
ProcessList::iterator prev = p_it;
|
416
|
+
prev--;
|
417
|
+
P_DEBUG("Garbage collect idle process: " << process->inspect() <<
|
418
|
+
", group=" << group->name);
|
419
|
+
group->detach(process, actions);
|
420
|
+
p_it = prev;
|
421
|
+
} else if (nextGcRunTime == 0
|
422
|
+
|| processGcTime < nextGcRunTime) {
|
423
|
+
nextGcRunTime = processGcTime;
|
424
|
+
}
|
425
|
+
}
|
426
|
+
|
427
|
+
group->verifyInvariants();
|
428
|
+
|
429
|
+
// ...cleanup the spawner if it's been idle for more than preloaderIdleTime.
|
430
|
+
if (group->spawner->cleanable()) {
|
431
|
+
unsigned long long spawnerGcTime =
|
432
|
+
group->spawner->lastUsed() +
|
433
|
+
group->options.getMaxPreloaderIdleTime() * 1000000;
|
434
|
+
if (now >= spawnerGcTime) {
|
435
|
+
P_DEBUG("Garbage collect idle spawner: group=" << group->name);
|
436
|
+
group->asyncCleanupSpawner();
|
437
|
+
} else if (nextGcRunTime == 0
|
438
|
+
|| spawnerGcTime < nextGcRunTime) {
|
439
|
+
nextGcRunTime = spawnerGcTime;
|
440
|
+
}
|
441
|
+
}
|
442
|
+
}
|
443
|
+
|
444
|
+
// ...remove entire supergroup if it has become garbage
|
445
|
+
// collectable after detaching idle processes.
|
446
|
+
if (superGroup->garbageCollectable(now)) {
|
447
|
+
superGroupsToDetach.push_back(superGroup);
|
448
|
+
}
|
449
|
+
|
450
|
+
superGroup->verifyInvariants();
|
451
|
+
}
|
452
|
+
|
453
|
+
vector<SuperGroupPtr>::const_iterator it2;
|
454
|
+
for (it2 = superGroupsToDetach.begin(); it2 != superGroupsToDetach.end(); it2++) {
|
455
|
+
P_DEBUG("Garbage collect SuperGroup: " << (*it2)->inspect());
|
456
|
+
detachSuperGroup(*it2, false, &actions);
|
457
|
+
}
|
458
|
+
|
459
|
+
verifyInvariants();
|
460
|
+
|
461
|
+
// Schedule next garbage collection run.
|
462
|
+
ev_tstamp tstamp;
|
463
|
+
if (nextGcRunTime == 0 || nextGcRunTime <= now) {
|
464
|
+
tstamp = maxIdleTime / 1000000.0;
|
465
|
+
} else {
|
466
|
+
tstamp = (nextGcRunTime - now) / 1000000.0;
|
467
|
+
}
|
468
|
+
P_DEBUG("Garbage collection done; next garbage collect in " <<
|
469
|
+
std::fixed << std::setprecision(3) << tstamp << " sec");
|
470
|
+
|
471
|
+
lock.unlock();
|
472
|
+
runAllActions(actions);
|
473
|
+
timer.start(tstamp, 0.0);
|
474
|
+
}
|
475
|
+
|
476
|
+
struct ProcessAnalyticsLogEntry {
|
477
|
+
string groupName;
|
478
|
+
string key;
|
479
|
+
stringstream data;
|
480
|
+
};
|
481
|
+
|
482
|
+
typedef shared_ptr<ProcessAnalyticsLogEntry> ProcessAnalyticsLogEntryPtr;
|
483
|
+
|
484
|
+
void collectAnalytics(ev::timer &timer, int revents) {
|
485
|
+
try {
|
486
|
+
realCollectAnalytics(timer);
|
487
|
+
} catch (const tracable_exception &e) {
|
488
|
+
P_WARN("ERROR: " << e.what() << "\n Backtrace:\n" << e.backtrace());
|
489
|
+
}
|
490
|
+
}
|
491
|
+
|
492
|
+
void realCollectAnalytics(ev::timer &timer) {
|
493
|
+
PoolPtr self = shared_from_this(); // Keep pool object alive.
|
494
|
+
TRACE_POINT();
|
495
|
+
this_thread::disable_interruption di;
|
496
|
+
this_thread::disable_syscall_interruption dsi;
|
497
|
+
vector<pid_t> pids;
|
498
|
+
unsigned int max;
|
499
|
+
|
500
|
+
// Collect all the PIDs.
|
501
|
+
{
|
502
|
+
UPDATE_TRACE_POINT();
|
503
|
+
LockGuard l(syncher);
|
504
|
+
max = this->max;
|
505
|
+
}
|
506
|
+
pids.reserve(max);
|
507
|
+
{
|
508
|
+
UPDATE_TRACE_POINT();
|
509
|
+
LockGuard l(syncher);
|
510
|
+
SuperGroupMap::const_iterator sg_it, sg_end = superGroups.end();
|
511
|
+
|
512
|
+
for (sg_it = superGroups.begin(); sg_it != sg_end; sg_it++) {
|
513
|
+
const SuperGroupPtr &superGroup = sg_it->second;
|
514
|
+
vector<GroupPtr>::const_iterator g_it, g_end = superGroup->groups.end();
|
515
|
+
|
516
|
+
for (g_it = superGroup->groups.begin(); g_it != g_end; g_it++) {
|
517
|
+
const GroupPtr &group = *g_it;
|
518
|
+
ProcessList::const_iterator p_it, p_end = group->processes.end();
|
519
|
+
|
520
|
+
for (p_it = group->processes.begin(); p_it != p_end; p_it++) {
|
521
|
+
const ProcessPtr &process = *p_it;
|
522
|
+
pids.push_back(process->pid);
|
523
|
+
}
|
524
|
+
|
525
|
+
p_end = group->disabledProcesses.end();
|
526
|
+
for (p_it = group->disabledProcesses.begin(); p_it != p_end; p_it++) {
|
527
|
+
const ProcessPtr &process = *p_it;
|
528
|
+
pids.push_back(process->pid);
|
529
|
+
}
|
530
|
+
}
|
531
|
+
}
|
532
|
+
}
|
533
|
+
|
534
|
+
ProcessMetricMap allMetrics;
|
535
|
+
try {
|
536
|
+
// Now collect the process metrics and store them in the
|
537
|
+
// data structures, and log the state into the analytics logs.
|
538
|
+
UPDATE_TRACE_POINT();
|
539
|
+
allMetrics = ProcessMetricsCollector().collect(pids);
|
540
|
+
} catch (const ProcessMetricsCollector::ParseException &) {
|
541
|
+
P_WARN("Unable to collect process metrics: cannot parse 'ps' output.");
|
542
|
+
goto end;
|
543
|
+
}
|
544
|
+
|
545
|
+
{
|
546
|
+
UPDATE_TRACE_POINT();
|
547
|
+
vector<ProcessAnalyticsLogEntryPtr> logEntries;
|
548
|
+
ScopedLock l(syncher);
|
549
|
+
SuperGroupMap::iterator sg_it, sg_end = superGroups.end();
|
550
|
+
|
551
|
+
UPDATE_TRACE_POINT();
|
552
|
+
for (sg_it = superGroups.begin(); sg_it != sg_end; sg_it++) {
|
553
|
+
const SuperGroupPtr &superGroup = sg_it->second;
|
554
|
+
vector<GroupPtr>::iterator g_it, g_end = superGroup->groups.end();
|
555
|
+
|
556
|
+
for (g_it = superGroup->groups.begin(); g_it != g_end; g_it++) {
|
557
|
+
const GroupPtr &group = *g_it;
|
558
|
+
ProcessList::iterator p_it, p_end = group->processes.end();
|
559
|
+
|
560
|
+
for (p_it = group->processes.begin(); p_it != p_end; p_it++) {
|
561
|
+
ProcessPtr &process = *p_it;
|
562
|
+
ProcessMetricMap::const_iterator metrics_it =
|
563
|
+
allMetrics.find(process->pid);
|
564
|
+
if (metrics_it != allMetrics.end()) {
|
565
|
+
process->metrics = metrics_it->second;
|
566
|
+
}
|
567
|
+
}
|
568
|
+
|
569
|
+
p_end = group->disabledProcesses.end();
|
570
|
+
for (p_it = group->disabledProcesses.begin(); p_it != p_end; p_it++) {
|
571
|
+
ProcessPtr &process = *p_it;
|
572
|
+
ProcessMetricMap::const_iterator metrics_it =
|
573
|
+
allMetrics.find(process->pid);
|
574
|
+
if (metrics_it != allMetrics.end()) {
|
575
|
+
process->metrics = metrics_it->second;
|
576
|
+
}
|
577
|
+
}
|
578
|
+
|
579
|
+
// Log to Union Station.
|
580
|
+
if (group->options.analytics && loggerFactory != NULL) {
|
581
|
+
ProcessAnalyticsLogEntryPtr entry = make_shared<ProcessAnalyticsLogEntry>();
|
582
|
+
stringstream &xml = entry->data;
|
583
|
+
|
584
|
+
entry->groupName = group->name;
|
585
|
+
entry->key = group->options.unionStationKey;
|
586
|
+
xml << "Group: <group>";
|
587
|
+
group->inspectXml(xml, false);
|
588
|
+
xml << "</group>";
|
589
|
+
}
|
590
|
+
}
|
591
|
+
}
|
592
|
+
|
593
|
+
l.unlock();
|
594
|
+
while (!logEntries.empty()) {
|
595
|
+
ProcessAnalyticsLogEntryPtr entry = logEntries.back();
|
596
|
+
logEntries.pop_back();
|
597
|
+
LoggerPtr logger = loggerFactory->newTransaction(entry->groupName,
|
598
|
+
"processes", entry->key);
|
599
|
+
logger->message(entry->data.str());
|
600
|
+
}
|
601
|
+
}
|
602
|
+
|
603
|
+
end:
|
604
|
+
// Sleep for about 4 seconds, aligned to seconds boundary
|
605
|
+
// for saving power on laptops.
|
606
|
+
ev_now_update(libev->getLoop());
|
607
|
+
unsigned long long currentTime = SystemTime::getUsec();
|
608
|
+
unsigned long long deadline =
|
609
|
+
roundUp<unsigned long long>(currentTime, 1000000) + 4000000;
|
610
|
+
timer.start((deadline - currentTime) / 1000000.0, 0.0);
|
611
|
+
}
|
612
|
+
|
613
|
+
SuperGroupPtr createSuperGroup(const Options &options) {
|
614
|
+
SuperGroupPtr superGroup = make_shared<SuperGroup>(shared_from_this(),
|
615
|
+
options);
|
616
|
+
superGroup->initialize();
|
617
|
+
superGroups.set(options.getAppGroupName(), superGroup);
|
618
|
+
return superGroup;
|
619
|
+
}
|
620
|
+
|
621
|
+
SuperGroupPtr createSuperGroupAndAsyncGetFromIt(const Options &options,
|
622
|
+
const GetCallback &callback)
|
623
|
+
{
|
624
|
+
SuperGroupPtr superGroup = createSuperGroup(options);
|
625
|
+
SessionPtr session = superGroup->get(options, callback);
|
626
|
+
/* Callback should now have been put on the wait list,
|
627
|
+
* unless something has changed and we forgot to update
|
628
|
+
* some code here...
|
629
|
+
*/
|
630
|
+
P_ASSERT(session == NULL);
|
631
|
+
return superGroup;
|
632
|
+
}
|
633
|
+
|
634
|
+
// Debugging helper function, implemented in .cpp file so that GDB can access it.
|
635
|
+
const SuperGroupPtr getSuperGroup(const char *name);
|
636
|
+
|
637
|
+
public:
|
638
|
+
Pool(SafeLibev *libev, const SpawnerFactoryPtr &spawnerFactory,
|
639
|
+
const LoggerFactoryPtr &loggerFactory = LoggerFactoryPtr(),
|
640
|
+
const RandomGeneratorPtr &randomGenerator = RandomGeneratorPtr())
|
641
|
+
{
|
642
|
+
this->libev = libev;
|
643
|
+
this->spawnerFactory = spawnerFactory;
|
644
|
+
this->loggerFactory = loggerFactory;
|
645
|
+
if (randomGenerator != NULL) {
|
646
|
+
this->randomGenerator = randomGenerator;
|
647
|
+
} else {
|
648
|
+
this->randomGenerator = make_shared<RandomGenerator>();
|
649
|
+
}
|
650
|
+
|
651
|
+
max = 6;
|
652
|
+
maxIdleTime = 60 * 1000000;
|
653
|
+
|
654
|
+
garbageCollectionTimer.set<Pool, &Pool::garbageCollect>(this);
|
655
|
+
garbageCollectionTimer.set(maxIdleTime / 1000000.0, 0.0);
|
656
|
+
libev->start(garbageCollectionTimer);
|
657
|
+
analyticsCollectionTimer.set<Pool, &Pool::collectAnalytics>(this);
|
658
|
+
analyticsCollectionTimer.set(3.0, 0.0);
|
659
|
+
libev->start(analyticsCollectionTimer);
|
660
|
+
|
661
|
+
spawnLoopIteration = 0;
|
662
|
+
}
|
663
|
+
|
664
|
+
~Pool() {
|
665
|
+
TRACE_POINT();
|
666
|
+
destroy();
|
667
|
+
}
|
668
|
+
|
669
|
+
void destroy() {
|
670
|
+
TRACE_POINT();
|
671
|
+
libev->stop(garbageCollectionTimer);
|
672
|
+
libev->stop(analyticsCollectionTimer);
|
673
|
+
|
674
|
+
UPDATE_TRACE_POINT();
|
675
|
+
interruptableThreads.interrupt_and_join_all();
|
676
|
+
nonInterruptableThreads.join_all();
|
677
|
+
|
678
|
+
UPDATE_TRACE_POINT();
|
679
|
+
ScopedLock l(syncher);
|
680
|
+
SuperGroupMap::iterator it;
|
681
|
+
vector<SuperGroupPtr>::iterator it2;
|
682
|
+
vector<SuperGroupPtr> superGroupsToDetach;
|
683
|
+
vector<Callback> actions;
|
684
|
+
for (it = superGroups.begin(); it != superGroups.end(); it++) {
|
685
|
+
superGroupsToDetach.push_back(it->second);
|
686
|
+
}
|
687
|
+
for (it2 = superGroupsToDetach.begin(); it2 != superGroupsToDetach.end(); it2++) {
|
688
|
+
detachSuperGroup(*it2, false, &actions);
|
689
|
+
}
|
690
|
+
|
691
|
+
verifyInvariants();
|
692
|
+
verifyExpensiveInvariants();
|
693
|
+
l.unlock();
|
694
|
+
runAllActions(actions);
|
695
|
+
|
696
|
+
// detachSuperGroup() may launch additional threads, so wait for them.
|
697
|
+
interruptableThreads.interrupt_and_join_all();
|
698
|
+
nonInterruptableThreads.join_all();
|
699
|
+
}
|
700
|
+
|
701
|
+
// 'lockNow == false' may only be used during unit tests. Normally we
|
702
|
+
// should never call the callback while holding the lock.
|
703
|
+
void asyncGet(const Options &options, const GetCallback &callback, bool lockNow = true) {
|
704
|
+
DynamicScopedLock lock(syncher, lockNow);
|
705
|
+
|
706
|
+
verifyInvariants();
|
707
|
+
P_TRACE(2, "asyncGet(appRoot=" << options.appRoot << ")");
|
708
|
+
|
709
|
+
SuperGroup *existingSuperGroup = findMatchingSuperGroup(options);
|
710
|
+
if (OXT_LIKELY(existingSuperGroup != NULL)) {
|
711
|
+
/* Best case: the app super group is already in the pool. Let's use it. */
|
712
|
+
P_TRACE(2, "Found existing SuperGroup");
|
713
|
+
existingSuperGroup->verifyInvariants();
|
714
|
+
SessionPtr session = existingSuperGroup->get(options, callback);
|
715
|
+
existingSuperGroup->verifyInvariants();
|
716
|
+
verifyInvariants();
|
717
|
+
P_TRACE(2, "asyncGet() finished");
|
718
|
+
if (lockNow) {
|
719
|
+
lock.unlock();
|
720
|
+
}
|
721
|
+
if (session != NULL) {
|
722
|
+
callback(session, ExceptionPtr());
|
723
|
+
}
|
724
|
+
|
725
|
+
} else if (!atFullCapacity(false)) {
|
726
|
+
/* The app super group isn't in the pool and we have enough free
|
727
|
+
* resources to make a new one.
|
728
|
+
*/
|
729
|
+
P_TRACE(2, "Spawning new SuperGroup");
|
730
|
+
SuperGroupPtr superGroup = createSuperGroupAndAsyncGetFromIt(options, callback);
|
731
|
+
superGroup->verifyInvariants();
|
732
|
+
verifyInvariants();
|
733
|
+
P_TRACE(2, "asyncGet() finished");
|
734
|
+
|
735
|
+
} else {
|
736
|
+
vector<Callback> actions;
|
737
|
+
|
738
|
+
/* Uh oh, the app super group isn't in the pool but we don't
|
739
|
+
* have the resources to make a new one. The sysadmin should
|
740
|
+
* configure the system to let something like this happen
|
741
|
+
* as least as possible, but let's try to handle it as well
|
742
|
+
* as we can.
|
743
|
+
*
|
744
|
+
* First, try to trash an idle process that's the oldest.
|
745
|
+
*/
|
746
|
+
P_TRACE(2, "Pool is at full capacity; trying to free a process...");
|
747
|
+
ProcessPtr process = findOldestIdleProcess();
|
748
|
+
if (process == NULL) {
|
749
|
+
/* All processes are doing something. We have no choice
|
750
|
+
* but to trash a non-idle process.
|
751
|
+
*/
|
752
|
+
if (options.allowTrashingNonIdleProcesses) {
|
753
|
+
process = findBestProcessToTrash();
|
754
|
+
}
|
755
|
+
} else {
|
756
|
+
// Check invariant.
|
757
|
+
P_ASSERT(process->getGroup()->getWaitlist.empty());
|
758
|
+
}
|
759
|
+
if (process == NULL) {
|
760
|
+
/* All (super)groups are currently initializing/restarting/spawning/etc
|
761
|
+
* so nothing can be killed. We have no choice but to satisfy this
|
762
|
+
* get() action later when resources become available.
|
763
|
+
*/
|
764
|
+
P_TRACE(2, "Could not free a process; putting request to getWaitlist");
|
765
|
+
getWaitlist.push_back(GetWaiter(options, callback));
|
766
|
+
} else {
|
767
|
+
GroupPtr group;
|
768
|
+
SuperGroupPtr superGroup;
|
769
|
+
|
770
|
+
P_TRACE(2, "Freeing process " << process->inspect());
|
771
|
+
group = process->getGroup();
|
772
|
+
P_ASSERT(group != NULL);
|
773
|
+
superGroup = group->getSuperGroup();
|
774
|
+
P_ASSERT(superGroup != NULL);
|
775
|
+
|
776
|
+
group->detach(process, actions);
|
777
|
+
if (superGroup->garbageCollectable()) {
|
778
|
+
P_ASSERT(group->garbageCollectable());
|
779
|
+
forceDetachSuperGroup(superGroup, actions);
|
780
|
+
P_ASSERT(superGroup->getWaitlist.empty());
|
781
|
+
} else if (group->processes.empty()
|
782
|
+
&& !group->spawning()
|
783
|
+
&& !group->getWaitlist.empty())
|
784
|
+
{
|
785
|
+
/* This group no longer has any processes - either
|
786
|
+
* spawning or alive - to satisfy its get waiters.
|
787
|
+
* We migrate the group's get wait list to the pool's
|
788
|
+
* get wait list. The group's original get waiters
|
789
|
+
* will get their chances later.
|
790
|
+
*/
|
791
|
+
migrateGroupGetWaitlistToPool(group);
|
792
|
+
}
|
793
|
+
group->verifyInvariants();
|
794
|
+
superGroup->verifyInvariants();
|
795
|
+
|
796
|
+
/* Now that a process has been trashed we can create
|
797
|
+
* the missing SuperGroup.
|
798
|
+
*/
|
799
|
+
superGroup = make_shared<SuperGroup>(shared_from_this(), options);
|
800
|
+
superGroup->initialize();
|
801
|
+
superGroups.set(options.getAppGroupName(), superGroup);
|
802
|
+
SessionPtr session = superGroup->get(options, callback);
|
803
|
+
/* The SuperGroup is still initializing so the callback
|
804
|
+
* should now have been put on the wait list,
|
805
|
+
* unless something has changed and we forgot to update
|
806
|
+
* some code here...
|
807
|
+
*/
|
808
|
+
P_ASSERT(session == NULL);
|
809
|
+
superGroup->verifyInvariants();
|
810
|
+
}
|
811
|
+
|
812
|
+
P_ASSERT(atFullCapacity(false));
|
813
|
+
verifyInvariants();
|
814
|
+
verifyExpensiveInvariants();
|
815
|
+
P_TRACE(2, "asyncGet() finished");
|
816
|
+
|
817
|
+
if (!actions.empty()) {
|
818
|
+
if (lockNow) {
|
819
|
+
lock.unlock();
|
820
|
+
runAllActions(actions);
|
821
|
+
} else {
|
822
|
+
// This state is not allowed. If we reach
|
823
|
+
// here then it probably indicates a bug in
|
824
|
+
// the test suite.
|
825
|
+
P_ABORT();
|
826
|
+
}
|
827
|
+
}
|
828
|
+
}
|
829
|
+
}
|
830
|
+
|
831
|
+
SessionPtr get(const Options &options, Ticket *ticket) {
|
832
|
+
ticket->session.reset();
|
833
|
+
ticket->exception.reset();
|
834
|
+
|
835
|
+
asyncGet(options, boost::bind(syncGetCallback, ticket, _1, _2));
|
836
|
+
|
837
|
+
ScopedLock lock(ticket->syncher);
|
838
|
+
while (ticket->session == NULL && ticket->exception == NULL) {
|
839
|
+
ticket->cond.wait(lock);
|
840
|
+
}
|
841
|
+
lock.unlock();
|
842
|
+
|
843
|
+
if (OXT_LIKELY(ticket->session != NULL)) {
|
844
|
+
SessionPtr session = ticket->session;
|
845
|
+
ticket->session.reset();
|
846
|
+
return session;
|
847
|
+
} else {
|
848
|
+
rethrowException(ticket->exception);
|
849
|
+
return SessionPtr(); // Shut up compiler warning.
|
850
|
+
}
|
851
|
+
}
|
852
|
+
|
853
|
+
GroupPtr findOrCreateGroup(const Options &options) {
|
854
|
+
Options options2 = options;
|
855
|
+
options2.noop = true;
|
856
|
+
|
857
|
+
Ticket ticket;
|
858
|
+
{
|
859
|
+
LockGuard l(syncher);
|
860
|
+
if (superGroups.get(options.getAppGroupName()) == NULL) {
|
861
|
+
// Forcefully create SuperGroup, don't care whether resource limits
|
862
|
+
// actually allow it.
|
863
|
+
createSuperGroup(options);
|
864
|
+
}
|
865
|
+
}
|
866
|
+
return get(options2, &ticket)->getProcess()->getGroup();
|
867
|
+
}
|
868
|
+
|
869
|
+
void setMax(unsigned int max) {
|
870
|
+
ScopedLock l(syncher);
|
871
|
+
P_ASSERT(max > 0);
|
872
|
+
verifyInvariants();
|
873
|
+
verifyExpensiveInvariants();
|
874
|
+
bool bigger = max > this->max;
|
875
|
+
this->max = max;
|
876
|
+
if (bigger) {
|
877
|
+
/* If there are clients waiting for resources
|
878
|
+
* to become free, spawn more processes now that
|
879
|
+
* we have the capacity.
|
880
|
+
*
|
881
|
+
* We favor waiters on the pool over waiters on the
|
882
|
+
* the groups because the latter already have the
|
883
|
+
* resources to eventually complete. Favoring waiters
|
884
|
+
* on the pool should be fairer.
|
885
|
+
*/
|
886
|
+
vector<Callback> actions;
|
887
|
+
assignSessionsToGetWaiters(actions);
|
888
|
+
possiblySpawnMoreProcessesForExistingGroups();
|
889
|
+
|
890
|
+
verifyInvariants();
|
891
|
+
verifyExpensiveInvariants();
|
892
|
+
l.unlock();
|
893
|
+
runAllActions(actions);
|
894
|
+
} else {
|
895
|
+
verifyInvariants();
|
896
|
+
verifyExpensiveInvariants();
|
897
|
+
}
|
898
|
+
}
|
899
|
+
|
900
|
+
void activateNewMaxIdleTime() {
|
901
|
+
LockGuard l(syncher);
|
902
|
+
garbageCollectionTimer.stop();
|
903
|
+
garbageCollectionTimer.start(maxIdleTime / 1000000.0, 0.0);
|
904
|
+
}
|
905
|
+
|
906
|
+
void setMaxIdleTime(unsigned long long value) {
|
907
|
+
{
|
908
|
+
LockGuard l(syncher);
|
909
|
+
maxIdleTime = value;
|
910
|
+
}
|
911
|
+
libev->run(boost::bind(&Pool::activateNewMaxIdleTime, this));
|
912
|
+
}
|
913
|
+
|
914
|
+
unsigned int utilization(bool lock = true) const {
|
915
|
+
DynamicScopedLock l(syncher, lock);
|
916
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
917
|
+
int result = 0;
|
918
|
+
for (it = superGroups.begin(); it != end; it++) {
|
919
|
+
const SuperGroupPtr &superGroup = it->second;
|
920
|
+
result += superGroup->utilization();
|
921
|
+
}
|
922
|
+
return result;
|
923
|
+
}
|
924
|
+
|
925
|
+
bool atFullCapacity(bool lock = true) const {
|
926
|
+
DynamicScopedLock l(syncher, lock);
|
927
|
+
return utilization(false) >= max;
|
928
|
+
}
|
929
|
+
|
930
|
+
vector<ProcessPtr> getProcesses() const {
|
931
|
+
LockGuard l(syncher);
|
932
|
+
vector<ProcessPtr> result;
|
933
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
934
|
+
for (it = superGroups.begin(); OXT_LIKELY(it != end); it++) {
|
935
|
+
const SuperGroupPtr &superGroup = it->second;
|
936
|
+
vector<GroupPtr> &groups = superGroup->groups;
|
937
|
+
vector<GroupPtr>::const_iterator g_it, g_end = groups.end();
|
938
|
+
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
939
|
+
const GroupPtr &group = *g_it;
|
940
|
+
ProcessList::const_iterator p_it;
|
941
|
+
|
942
|
+
for (p_it = group->processes.begin(); p_it != group->processes.end(); p_it++) {
|
943
|
+
result.push_back(*p_it);
|
944
|
+
}
|
945
|
+
for (p_it = group->disabledProcesses.begin(); p_it != group->disabledProcesses.end(); p_it++) {
|
946
|
+
result.push_back(*p_it);
|
947
|
+
}
|
948
|
+
}
|
949
|
+
}
|
950
|
+
return result;
|
951
|
+
}
|
952
|
+
|
953
|
+
unsigned int getProcessCount(bool lock = true) const {
|
954
|
+
DynamicScopedLock l(syncher, lock);
|
955
|
+
unsigned int result = 0;
|
956
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
957
|
+
for (it = superGroups.begin(); OXT_LIKELY(it != end); it++) {
|
958
|
+
const SuperGroupPtr &superGroup = it->second;
|
959
|
+
result += superGroup->getProcessCount();
|
960
|
+
}
|
961
|
+
return result;
|
962
|
+
}
|
963
|
+
|
964
|
+
SuperGroupPtr findSuperGroupBySecret(const string &secret, bool lock = true) const {
|
965
|
+
DynamicScopedLock l(syncher, lock);
|
966
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
967
|
+
for (it = superGroups.begin(); OXT_LIKELY(it != end); it++) {
|
968
|
+
const SuperGroupPtr &superGroup = it->second;
|
969
|
+
if (superGroup->secret == secret) {
|
970
|
+
return superGroup;
|
971
|
+
}
|
972
|
+
}
|
973
|
+
return SuperGroupPtr();
|
974
|
+
}
|
975
|
+
|
976
|
+
ProcessPtr findProcessByGupid(const string &gupid, bool lock = true) const {
|
977
|
+
DynamicScopedLock l(syncher, lock);
|
978
|
+
SuperGroupMap::const_iterator it, end = superGroups.end();
|
979
|
+
for (it = superGroups.begin(); OXT_LIKELY(it != end); it++) {
|
980
|
+
const SuperGroupPtr &superGroup = it->second;
|
981
|
+
vector<GroupPtr> &groups = superGroup->groups;
|
982
|
+
vector<GroupPtr>::const_iterator g_it, g_end = groups.end();
|
983
|
+
for (g_it = groups.begin(); g_it != g_end; g_it++) {
|
984
|
+
const GroupPtr &group = *g_it;
|
985
|
+
const ProcessList &processes = group->processes;
|
986
|
+
ProcessList::const_iterator p_it, p_end = processes.end();
|
987
|
+
for (p_it = processes.begin(); p_it != p_end; p_it++) {
|
988
|
+
const ProcessPtr &process = *p_it;
|
989
|
+
if (process->gupid == gupid) {
|
990
|
+
return process;
|
991
|
+
}
|
992
|
+
}
|
993
|
+
}
|
994
|
+
}
|
995
|
+
return ProcessPtr();
|
996
|
+
}
|
997
|
+
|
998
|
+
bool detachSuperGroup(const SuperGroupPtr &superGroup, bool lock = true,
|
999
|
+
vector<Callback> *postLockActions = NULL)
|
1000
|
+
{
|
1001
|
+
P_ASSERT(lock || postLockActions != NULL);
|
1002
|
+
DynamicScopedLock l(syncher, lock);
|
1003
|
+
|
1004
|
+
if (OXT_LIKELY(superGroup->getPool().get() == this)) {
|
1005
|
+
if (OXT_LIKELY(superGroups.get(superGroup->name) != NULL)) {
|
1006
|
+
verifyInvariants();
|
1007
|
+
verifyExpensiveInvariants();
|
1008
|
+
|
1009
|
+
vector<Callback> actions;
|
1010
|
+
|
1011
|
+
forceDetachSuperGroup(superGroup, actions);
|
1012
|
+
/* If this SuperGroup had get waiters, either
|
1013
|
+
* on itself or in one of its groups, then we must
|
1014
|
+
* reprocess them immediately. Detaching such a
|
1015
|
+
* SuperGroup is essentially the same as restarting it.
|
1016
|
+
*/
|
1017
|
+
migrateSuperGroupGetWaitlistToPool(superGroup);
|
1018
|
+
|
1019
|
+
assignSessionsToGetWaiters(actions);
|
1020
|
+
possiblySpawnMoreProcessesForExistingGroups();
|
1021
|
+
|
1022
|
+
verifyInvariants();
|
1023
|
+
verifyExpensiveInvariants();
|
1024
|
+
|
1025
|
+
if (lock) {
|
1026
|
+
l.unlock();
|
1027
|
+
runAllActions(actions);
|
1028
|
+
} else if (postLockActions->empty()) {
|
1029
|
+
*postLockActions = actions;
|
1030
|
+
} else {
|
1031
|
+
postLockActions->reserve(postLockActions->size() +
|
1032
|
+
actions.size());
|
1033
|
+
for (unsigned int i = 0; i < actions.size(); i++) {
|
1034
|
+
postLockActions->push_back(actions[i]);
|
1035
|
+
}
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
return true;
|
1039
|
+
} else {
|
1040
|
+
return false;
|
1041
|
+
}
|
1042
|
+
} else {
|
1043
|
+
return false;
|
1044
|
+
}
|
1045
|
+
}
|
1046
|
+
|
1047
|
+
bool detachProcess(const ProcessPtr &process) {
|
1048
|
+
ScopedLock l(syncher);
|
1049
|
+
vector<Callback> actions;
|
1050
|
+
bool result = detachProcessUnlocked(process, actions);
|
1051
|
+
l.unlock();
|
1052
|
+
runAllActions(actions);
|
1053
|
+
return result;
|
1054
|
+
}
|
1055
|
+
|
1056
|
+
bool detachSuperGroup(const string &superGroupSecret) {
|
1057
|
+
LockGuard l(syncher);
|
1058
|
+
SuperGroupPtr superGroup = findSuperGroupBySecret(superGroupSecret, false);
|
1059
|
+
if (superGroup != NULL) {
|
1060
|
+
return detachSuperGroup(superGroup, false);
|
1061
|
+
} else {
|
1062
|
+
return false;
|
1063
|
+
}
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
bool detachProcess(const string &gupid) {
|
1067
|
+
ScopedLock l(syncher);
|
1068
|
+
ProcessPtr process = findProcessByGupid(gupid, false);
|
1069
|
+
if (process != NULL) {
|
1070
|
+
vector<Callback> actions;
|
1071
|
+
bool result = detachProcessUnlocked(process, actions);
|
1072
|
+
l.unlock();
|
1073
|
+
runAllActions(actions);
|
1074
|
+
return result;
|
1075
|
+
} else {
|
1076
|
+
return false;
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
|
1080
|
+
string inspect(const InspectOptions &options = InspectOptions(), bool lock = true) const {
|
1081
|
+
DynamicScopedLock l(syncher, lock);
|
1082
|
+
stringstream result;
|
1083
|
+
const char *headerColor = maybeColorize(options, ANSI_COLOR_YELLOW ANSI_COLOR_BLUE_BG ANSI_COLOR_BOLD);
|
1084
|
+
const char *resetColor = maybeColorize(options, ANSI_COLOR_RESET);
|
1085
|
+
|
1086
|
+
result << headerColor << "----------- General information -----------" << resetColor << endl;
|
1087
|
+
result << "Max pool size : " << max << endl;
|
1088
|
+
result << "Processes : " << getProcessCount(false) << endl;
|
1089
|
+
result << "Requests in queue : " << getWaitlist.size() << endl;
|
1090
|
+
//result << "active = " << active << endl;
|
1091
|
+
//result << "inactive = " << inactiveApps.size() << endl;
|
1092
|
+
result << endl;
|
1093
|
+
|
1094
|
+
result << headerColor << "----------- Application groups -----------" << resetColor << endl;
|
1095
|
+
SuperGroupMap::const_iterator sg_it, sg_end = superGroups.end();
|
1096
|
+
for (sg_it = superGroups.begin(); sg_it != sg_end; sg_it++) {
|
1097
|
+
const SuperGroupPtr &superGroup = sg_it->second;
|
1098
|
+
const Group *group = superGroup->defaultGroup;
|
1099
|
+
ProcessList::const_iterator p_it;
|
1100
|
+
|
1101
|
+
if (group != NULL) {
|
1102
|
+
result << group->name << ":" << endl;
|
1103
|
+
result << " App root: " << group->options.appRoot << endl;
|
1104
|
+
if (group->spawning()) {
|
1105
|
+
result << " (spawning new process...)" << endl;
|
1106
|
+
}
|
1107
|
+
result << " Requests in queue: " << group->getWaitlist.size() << endl;
|
1108
|
+
for (p_it = group->processes.begin(); p_it != group->processes.end(); p_it++) {
|
1109
|
+
const ProcessPtr &process = *p_it;
|
1110
|
+
char buf[128];
|
1111
|
+
|
1112
|
+
snprintf(buf, sizeof(buf),
|
1113
|
+
"* PID: %-5lu Sessions: %-2u Processed: %-5u Uptime: %s",
|
1114
|
+
(unsigned long) process->pid,
|
1115
|
+
process->sessions,
|
1116
|
+
process->processed,
|
1117
|
+
process->uptime().c_str());
|
1118
|
+
result << " " << buf << endl;
|
1119
|
+
const Socket *socket;
|
1120
|
+
if (options.verbose && (socket = process->sockets->findSocketWithName("http")) != NULL) {
|
1121
|
+
result << " URL : http://" << replaceString(socket->address, "tcp://", "") << endl;
|
1122
|
+
result << " Password: " << process->connectPassword << endl;
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
result << endl;
|
1126
|
+
}
|
1127
|
+
}
|
1128
|
+
return result.str();
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
string toXml(bool includeSecrets = true) const {
|
1132
|
+
LockGuard l(syncher);
|
1133
|
+
stringstream result;
|
1134
|
+
SuperGroupMap::const_iterator sg_it;
|
1135
|
+
vector<GroupPtr>::const_iterator g_it;
|
1136
|
+
ProcessList::const_iterator p_it;
|
1137
|
+
|
1138
|
+
result << "<?xml version=\"1.0\" encoding=\"iso8859-1\" ?>\n";
|
1139
|
+
result << "<info version=\"2\">";
|
1140
|
+
|
1141
|
+
result << "<process_count>" << getProcessCount(false) << "</process_count>";
|
1142
|
+
result << "<max>" << max << "</max>";
|
1143
|
+
result << "<utilization>" << utilization(false) << "</utilization>";
|
1144
|
+
result << "<get_wait_list_size>" << getWaitlist.size() << "</get_wait_list_size>";
|
1145
|
+
|
1146
|
+
result << "<supergroups>";
|
1147
|
+
for (sg_it = superGroups.begin(); sg_it != superGroups.end(); sg_it++) {
|
1148
|
+
const SuperGroupPtr &superGroup = sg_it->second;
|
1149
|
+
|
1150
|
+
result << "<name>" << escapeForXml(superGroup->name) << "</name>";
|
1151
|
+
result << "<state>" << superGroup->getStateName() << "</state>";
|
1152
|
+
result << "<get_wait_list_size>" << superGroup->getWaitlist.size() << "</get_wait_list_size>";
|
1153
|
+
result << "<utilization>" << superGroup->utilization() << "</utilization>";
|
1154
|
+
if (includeSecrets) {
|
1155
|
+
result << "<secret>" << escapeForXml(superGroup->secret) << "</secret>";
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
for (g_it = superGroup->groups.begin(); g_it != superGroup->groups.end(); g_it++) {
|
1159
|
+
const GroupPtr &group = *g_it;
|
1160
|
+
|
1161
|
+
if (group->componentInfo.isDefault) {
|
1162
|
+
result << "<group default=\"true\">";
|
1163
|
+
} else {
|
1164
|
+
result << "<group>";
|
1165
|
+
}
|
1166
|
+
group->inspectXml(result, includeSecrets);
|
1167
|
+
result << "</group>";
|
1168
|
+
}
|
1169
|
+
}
|
1170
|
+
result << "</supergroups>";
|
1171
|
+
|
1172
|
+
result << "</info>";
|
1173
|
+
return result.str();
|
1174
|
+
}
|
1175
|
+
};
|
1176
|
+
|
1177
|
+
|
1178
|
+
} // namespace ApplicationPool2
|
1179
|
+
} // namespace Passenger
|
1180
|
+
|
1181
|
+
#endif /* _PASSENGER_APPLICATION_POOL2_POOL_H_ */
|