1. 01 Mar, 2024 1 commit
    • Monty's avatar
      Fixed memory leaks in embedded server and mysqltest · 33dcf815
      Monty authored
      This commit fixes the following issues:
      - memory leak checking enabled for mysqltest. This cover all cases except
        calls to 'die()' that only happens in case of internal failures in
        mysqltest. die() is not called anymore in the result files differs.
      - One can now run mtr --embedded without failures (this crashed or hang
        before)
      - cleanup_and_exit() has a new parameter that indicates that it is called
        from die(), in which case we should not do memory leak checks. We now
        always call cleanup_and_exit() instead of exit() to be able to free up
        memory and discover memory leaks.
      - Lots of new assert to catch error conditions
      - More DBUG statements.
      - Fixed that all results are freed in mysqltest (Fixed a memory leak in
        mysqltest when using prepared statements).
      - Fixed race condition in do_stmt_close() that caused embedded server
        to not free memory. (Memory leak in mysqltest with embedded server).
      - Fixed two memory leaks in embedded server when using prepared statements.
        These memory leaks caused timeout hangs in mtr when server was compiled
        with safemalloc. This issue was not noticed (except as timeouts) as
        memory report checking was done but output of it was disabled.
      33dcf815
  2. 29 Feb, 2024 1 commit
    • Brandon Nesterenko's avatar
      MDEV-33546: Rpl_semi_sync_slave_status is ON When Replication Is Not Configured · bd604add
      Brandon Nesterenko authored
      If a server has a default configuration (e.g. in a my.cnf file) with
      rpl_semi_sync_slave_enabled set, on server start, the corresponding
      rpl_semi_sync_slave_status variable will also be ON initially, even
      if the slave was never configured/started. This is because the
      Repl_semi_sync_slave initialization logic (function init_object())
      sets the running status to the enabled value during
      init_server_components().
      
      This patch fixes this by removing the statement which sets the
      semi-sync slave running status from the initialization logic. An
      additional change needed from this is to semi-sync recovery: this
      status variable was used as a condition to determine binlog
      truncation during server recovery. This patch also switches this
      condition to reference the global rpl_semi_sync_slave_enabled
      variable. Though note, the semi-sync recovery condition is to be
      changed entirely with the MDEV-33424 agenda.
      
      Reviewed By:
      ============
      Andrei Elkin <andrei.elkin@mariadb.com>
      bd604add
  3. 28 Feb, 2024 2 commits
    • Sergei Petrunia's avatar
      MDEV-33502: part#4: Dont make redundant extra(HA_EXTRA_[NO]_KEYREAD) calls · 31463f11
      Sergei Petrunia authored
      In most cases, ha_partition forwards calls to extra() to all
      locked_partitions. It doesn't make sense to forward some calls for
      partitions that were pruned away.
      This patch introduces ha_partition::loop_read_partitions and makes
      these calls use it:
      
      - ha_partition::extra_opt(HA_EXTRA_KEYREAD)
      - ha_partition::extra(HA_EXTRA_KEYREAD)
      - ha_partition::extra(HA_EXTRA_NO_KEYREAD)
      
      Reviewed-by: Monty
      31463f11
    • Marko Mäkelä's avatar
      MDEV-33508 Performance regression due to frequent scan of full buf_pool.flush_list · 0772ac1f
      Marko Mäkelä authored
      buf_flush_page_cleaner(): Remove a loop that had originally been added
      in commit 9d146652 (MDEV-32029) and made
      redundant by commit 5b53342a (MDEV-32588).
      
      Starting with commit d34479dc (MDEV-33053)
      this loop would cause a significant performance regression in workloads
      where buf_pool.need_LRU_eviction() constantly holds in
      buf_flush_page_cleaner().
      
      Thanks to Steve Shaw of Intel for noticing this.
      
      Reviewed by: Debarun Banerjee
      Tested by: Matthias Leich
      0772ac1f
  4. 27 Feb, 2024 7 commits
    • Monty's avatar
    • Monty's avatar
      Fixed crash in connect.misc with embedded server · 89aae15d
      Monty authored
      The problem was that connect tried to recusiverly call
      emb_advanced_command(), which was not supported.
      
      Fixed by adding support for recursive calls.
      89aae15d
    • Monty's avatar
      Updated test cases result for s3.parition · 0c079f4f
      Monty authored
      MDEV-21472 ALTER TABLE ... ANALYZE PARTITION ... with EITS reads and locks all rows
      0c079f4f
    • Monty's avatar
      Optimize performance of my_bitmap · b5d65fc1
      Monty authored
      MDEV-33502 Slowdown when running nested statement with many partitions
      
      This change was triggered to help some MariaDB users with close to
      10000 bits in their bitmaps.
      
      - Change underlaying storage to be 64 bit instead of 32bit.
        - This reduses number of loops to scan bitmaps.
        - This can cause some bitmaps to be 4 byte large.
      - Ensure that all not used top-bits are always 0 (simplifes code as
        the last 64 bit storage is not a special case anymore).
      - Use my_find_first_bit() to find the first set bit which is much faster
        than scanning trough things byte by byte and then bit by bit.
      
      Other things:
      - Added a bool to remember if my_bitmap_init() did allocate the bitmap
        array. my_bitmap_free() will only free arrays it did allocate.
        This allowed me to remove setting 'bitmap=0' before calling
        my_bitmap_free() for cases where the bitmap's where allocated externally.
      - my_bitmap_init() sets bitmap to 0 in case of failure.
      - Added 'universal' asserts to most bitmap functions.
      - Change all remaining calls to bitmap_init() to my_bitmap_init().
        - To finish the change from 2014.
      - Changed all usage of uint32 in my_bitmap.h to my_bitmap_map.
      - Updated bitmap_copy() to handle bitmaps of different size.
      - Removed const from bitmap_exists_intersection() as this caused casts
        on all usage.
      - Removed not used function bitmap_set_above().
      - Renamed create_last_word_mask() to create_last_bit_mask() (to match
        name changes in my_bitmap.cc)
      - Extended bitmap-t with test for more bitmap functions.
      b5d65fc1
    • Monty's avatar
      Optimize handler_stats_disable() when handler_stats are already disabled · d4e1731f
      Monty authored
      MDEV-33502 Slowdown when running nested statement with many partitions
      d4e1731f
    • Monty's avatar
      Have ha_partition ignore HA_EXTRA..CHILDREN extra() calls if no myisamrg · a8f6b86c
      Monty authored
      MDEV-33502 Slowdown when running nested statement with many partitions
      
      Optimization for tables with a lot of partitions
      a8f6b86c
    • Marko Mäkelä's avatar
      MDEV-24671 fixup: Remove srv_max_n_threads · 71834ccb
      Marko Mäkelä authored
      The variable srv_max_n_threads lost its usefulness in
      commit db006a9a (MDEV-21452)
      and commit e71e6133 (MDEV-24671).
      71834ccb
  5. 26 Feb, 2024 1 commit
    • Thirunarayanan Balathandayuthapani's avatar
      MDEV-14193 innodb.log_file_name failed in buildbot with exception · 2c5f3bbe
      Thirunarayanan Balathandayuthapani authored
      Problem:
      =======
      - innodb.log_file_name fails if it executes after
      innodb.lock_insert_into_empty in few cases.
      innodb.lock_insert_into_empty test case failed to
      cleanup the table t2. Rollback of create..select fails
      to remove the table when it fails to acquire the
      innodb statistics table. This leads to rename table
      in log_file_name test case fails.
      
      Solution:
      ========
      - Cleanup the table t2 explictly after resetting
      innodb_lock_wait_timeout variable in
      innodb.lock_insert_into_empty test case.
      2c5f3bbe
  6. 23 Feb, 2024 2 commits
  7. 22 Feb, 2024 1 commit
    • Thirunarayanan Balathandayuthapani's avatar
      MDEV-33462 Server aborts while altering an InnoDB statistics table · e66928ab
      Thirunarayanan Balathandayuthapani authored
      Problem:
      =======
      - When online alter of InnoDB statistics table happens,
      any transaction which updates the statistics table
      has to read the undo log and log the DML changes during
      transaction commit. Applying undo log
      (UndorecApplier::apply_undo_rec) requires a shared
      lock on dictionary cache but dict_stats_save() already
      holds write lock on dictionary cache. This leads to
      abort of server during commit of statistics table changes.
      
      Solution:
      ========
      - Disallow LOCK=NONE operation for the InnoDB statistics table.
      The reasoning is that statistics tables are typically
      rather small, so any blocking would be rather short.
      Writes to the statistics tables should be a rare operation.
      e66928ab
  8. 21 Feb, 2024 1 commit
    • Marko Mäkelä's avatar
      MDEV-24167 fixup: srw_lock_debug for SUX_LOCK_GENERIC · 042c3fc4
      Marko Mäkelä authored
      srw_lock_debug::have_rd(), srw_lock_debug::have_wr():
      For SUX_LOCK_GENERIC (no futex based synchronization primitives),
      we cannot check if the underlying srw_lock is held by us.
      
      Thanks to Dmitry Shulga for pointing out this build failure.
      042c3fc4
  9. 20 Feb, 2024 1 commit
    • Thirunarayanan Balathandayuthapani's avatar
      MDEV-30655 IMPORT TABLESPACE fails with column count or index count mismatch · 903ae300
      Thirunarayanan Balathandayuthapani authored
      Problem:
      ========
      Currently import operation fails with schema mismatch when
      cfg file has hidden fts document id and hidden fts document index.
      
      Fix:
      ====
      To fix this issue, simply add the fts doc id column,
      indexes in table definition and try to import the table.
      In case of success:
      1) update the fts document id in sys columns.
      2) update the number of columns in sys tables.
      3) insert the new fts index entry in sys indexes table
      and sys fields.
      4) Reload the table with new table definition
      903ae300
  10. 19 Feb, 2024 1 commit
  11. 15 Feb, 2024 1 commit
  12. 13 Feb, 2024 10 commits
    • Marko Mäkelä's avatar
      Merge 10.5 into 10.6 · 691f9239
      Marko Mäkelä authored
      691f9239
    • Marko Mäkelä's avatar
      Merge 10.4 into 10.5 · b770633e
      Marko Mäkelä authored
      b770633e
    • Marko Mäkelä's avatar
      MDEV-33332 SIGSEGV in buf_read_ahead_linear() when bpage is in buf_pool.watch · 68d9deb6
      Marko Mäkelä authored
      buf_read_ahead_linear(): If buf_pool.watch_is_sentinel(*bpage),
      do not attempt to read the page frame because the pointer would be null
      for the elements of buf_pool.watch[].
      
      Hitting this bug requires the use of a non-default value of
      innodb_change_buffering.
      68d9deb6
    • Marko Mäkelä's avatar
      Fix GCC 14 -Wcalloc-transposed-args · d86deee3
      Marko Mäkelä authored
      d86deee3
    • Otto Kekäläinen's avatar
      Properly introduce wsrep_sst_backup script in project packaging · d64ade30
      Otto Kekäläinen authored
      The script wsrep_sst_backup was introduced on MariaDB 10.3 in commit
      9b2fa2ae. The new script was automatically included in RPM packages but not
      in Debian packages (which started to fail on warning about stray file).
      
      Include wsrep_sst_backup in the mariadb-server-10.5+ package, and also
      include a stub man page so that packaging of a new script is complete.
      
      Related:
      https://galeracluster.com/documentation/html_docs_20210213-1355-master/documentation/backup-cluster.html
      
      This commit was originally submitted in May 2022 in
      https://github.com/MariaDB/server/pull/2129 but upstream indicated only
      in May 2023 that it might get merged, thus this is for a later release.
      
      All new code of the whole pull request, including one or several files
      that are either new files or modified ones, are contributed under the
      BSD-new license. I am contributing on behalf of my employer Amazon Web
      Services, Inc.
      d64ade30
    • Oleksandr Byelkin's avatar
      fix view protocol in MDEV-29179 · ae709b64
      Oleksandr Byelkin authored
      ae709b64
    • Jan Tojnar's avatar
      MDEV-33439 Fix build with libxml2 2.12 · cae18632
      Jan Tojnar authored
      libxml2 2.12.0 made `xmlGetLastError()` return `const` pointer:
      
      https://gitlab.gnome.org/GNOME/libxml2/-/commit/61034116d0a3c8b295c6137956adc3ae55720711
      
      Clang 16 does not like this:
      
          error: assigning to 'xmlErrorPtr' (aka '_xmlError *') from 'const xmlError *' (aka 'const _xmlError *') discards qualifiers
          error: cannot initialize a variable of type 'xmlErrorPtr' (aka '_xmlError *') with an rvalue of type 'const xmlError *' (aka 'const _xmlError *')
      
      Let’s update the variables to `const`.
      For older versions, it will be automatically converted.
      
      But then `xmlResetError(xmlError*)` will not like the `const` pointer:
      
          error: no matching function for call to 'xmlResetError'
          note: candidate function not viable: 1st argument ('const xmlError *' (aka 'const _xmlError *')) would lose const qualifier
      
      Let’s replace it with `xmlResetLastError()`.
      
      ALso remove `LIBXMLDOC::Xerr` protected member property.
      It was introduced in 65b0e545
      along with the `xmlResetError` calls.
      It does not appear to be used for anything.
      cae18632
    • Sean Adams's avatar
      MDEV-24507: Server Crash using UDF in WHERE clause of VIEW · 3281b6b8
      Sean Adams authored
      These changes are submitted under the BSD 3-clause License.
      
      The original ticket describes a server crash when using a UDF in the WHERE clause of a view.  The crash also happens when using a UDF in the WHERE clause of a SELECT that uses a sub-query in the FROM clause.
      
      When the UDF does not have a _deinit function the server crashes in udf_handler::cleanup (sql/item_func.cc:3467).
      When the UDF has both an _init and a _deinit function but _init does not allocate memory for initid->ptr the server crashes in udf_handler::cleanup (sql/item_func.cc:3467).
      When the UDF has both an _init and a _deinit function and allocates/deallocates  memory for initid->ptr the server crashes in the memory deallocation of the _deinit function.
      
      The sequence of events seen are:
        1. A UDF, U, is created for the query.
        2. The UDF _init function is called using U->initid.
        3. U is cloned for the sub-query using the [default|implicit] copy constructor, resulting in V.
        4. The UDF _init function is called using V->initid.  U->initid and V->initid are the same value.
        5. The UDF function is called.
        6. The UDF _deinit function is called using U->initid.  If any memory was allocated for initid->ptr it is deallocated here.
        7. udf_handler::cleanup deletes the U->buffers String array.
        8. The UDF _deinit function is called using V->initid.  If any memory was allocated for initid->ptr it was previously deallocated and _deinit crashes the server.
        9. udf_handler::cleanup deletes the V->buffers String array. V->buffers was the same values as U->buffers which was already deallocated.  The server crashes.
      
      The solution is to create a[n explicit] copy constructor for udf_handler which sets not_original to true.  Later, not_original is set back to false (0) after udf_handler::fix_fields has set up a new value for initid->ptr.
      3281b6b8
    • Daniel Black's avatar
      MDEV-28419 subsequent runs of debian/autobake-deb.sh are not idempotent · c0f6c4bd
      Daniel Black authored
      While a -f debian/mariadb-plugin-columnstore.install idempotent check
      existed, the tying of the install file to the control file has some
      weaknesses.
      
      Used sed as an alternative to replace the debian/control
      mariadb-plugin-columnstore package defination and replace it with the
      one from the columnstore submodule.
      c0f6c4bd
    • Trevor Gross's avatar
      Fix a case of `unused-but-set-variable` · b909b525
      Trevor Gross authored
      The `unused-but-set-variable` warning is raised on MacOS from the
      `posix_fadvise` standin macro, since offset is often otherwise unused. Add a
      cast to absorb this warning.
      Signed-off-by: default avatarTrevor Gross <tmgross@umich.edu>
      b909b525
  13. 12 Feb, 2024 11 commits
    • Brad Smith's avatar
      Fix timeout(1) usage in wsrep_sst_mariabackup on *BSD · 44f5fa2d
      Brad Smith authored
      Also fix the usage of timeout(1) on NetBSD, OpenBSD and DragonFly.
      44f5fa2d
    • Marko Mäkelä's avatar
      MDEV-30528 CREATE FULLTEXT INDEX assertion failure WITH SYSTEM VERSIONING · ca88eac8
      Marko Mäkelä authored
      ha_innobase::check_if_supported_inplace_alter(): Require ALGORITHM=COPY
      when creating a FULLTEXT INDEX on a versioned table.
      
      row_merge_buf_add(), row_merge_read_clustered_index(): Remove the parameter
      or local variable history_fts that had been added in the attempt to fix
      MDEV-25004.
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      Tested by: Matthias Leich
      ca88eac8
    • Yuchen Pei's avatar
      MDEV-33441 Do not deinit plugin variables when retry requested · c37216de
      Yuchen Pei authored
      After MDEV-31400, plugins are allowed to ask for retries when failing
      initialisation. However, such failures also cause plugin system
      variables to be deleted (plugin_variables_deinit()) before retrying
      and are not re-added during retry.
      
      We fix this by checking that if the plugin has requested a retry the
      variables are not deleted. Because plugin_deinitialize() also calls
      plugin_variables_deinit(), if the retry fails, the variables will
      still be deleted.
      
      Alternatives considered:
      
      - remove the plugin_variables_deinit() from plugin_initialize() error
      handling altogether. We decide to take a more conservative approach
      here.
      
      - re-add the system variables during retry. It is more complicated
      than simply iterating over plugin->system_vars and call
      my_hash_insert(). For example we will need to assign values to
      the test_load field and extract more code from test_plugin_options(),
      if that is possible.
      c37216de
    • Marko Mäkelä's avatar
      MDEV-33383: Corrupted red-black tree due to incorrect comparison · 81f3e97b
      Marko Mäkelä authored
      fts_doc_id_cmp(): Replaces several duplicated functions for
      comparing two doc_id_t*. On IA-32, AMD64, ARMv7, ARMv8, RISC-V
      this should make use of some conditional ALU instructions.
      On POWER there will be conditional jumps. Unlike the original
      functions, these will return the correct result even if the
      difference of the two doc_id does not fit in the int data type.
      We use static_assert() and offsetof() to check at compilation time
      that this function is compatible with the rbt_create() calls.
      
      fts_query_compare_rank(): As documented, return -1 and not 1
      when the rank are equal and r1->doc_id < r2->doc_id. This will
      affect the result of ha_innobase::ft_read().
      
      fts_ptr2_cmp(), fts_ptr1_ptr2_cmp(): These replace
      fts_trx_table_cmp(), fts_trx_table_id_cmp().
      The fts_savepoint_t::tables will be sorted by dict_table_t*
      rather than dict_table_t::id. There was no correctness bug in
      the previous comparison predicates. We can avoid one level of
      unnecessary pointer dereferencing in this way.
      Actually, fts_savepoint_t is duplicating trx_t::mod_tables.
      MDEV-33401 was filed about removing it.
      
      The added unit test innodb_rbt-t covers both the previous buggy comparison
      predicate and the revised fts_doc_id_cmp(), using keys which led to
      finding the bug. Thanks to Shaohua Wang from Alibaba for providing the
      example and the revised comparison predicate.
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      81f3e97b
    • Marko Mäkelä's avatar
      Cleanup: Remove changed_pages_bitmap · 92f87f2c
      Marko Mäkelä authored
      The innodb_changed_pages plugin only was part of XtraDB, never InnoDB.
      It would be useful for incremental backups.
      We will remove the code from mariadb-backup for now, because it cannot
      serve any useful purpose until the server part has been implemented.
      92f87f2c
    • Marko Mäkelä's avatar
      MDEV-33383: Replace fts_doc_id_cmp, ib_vector_sort · 47122a61
      Marko Mäkelä authored
      fts_doc_ids_sort(): Sort an array of doc_id_t by C++11 std::sort().
      
      fts_doc_id_cmp(), ib_vector_sort(): Remove. The comparison was
      returning an incorrect result when the difference exceeded the int range.
      
      Reviewed by: Thirunarayanan Balathandayuthapani
      47122a61
    • Monty's avatar
      MDEV-33306 Optimizer choosing incorrect index in 10.6, 10.5 but not in 10.4 · 3907345e
      Monty authored
      In MariaDB up to 10.11, the test_if_cheaper_ordering() code (that tries
      to optimizer how GROUP BY is executed) assumes that if a table scan is used
      then if there is any index usable by GROUP BY it will be used.
      
      The reason MySQL 10.4 provides a better plan is because of two differences:
      - Plans using 'ref' has a cost of 1/10 of what it should be (as a
        protection against table scans). This is why 'ref' is used in 10.4
        and not in 10.5.
      - When 'ref' is used, then GROUP BY will not use an index for GROUP BY.
      
      In MariaDB 10.5 the chosen plan is a table scan (as it calculated to be
      faster) but as 'ref' is not used, the test_if_cheaper_ordering()
      optimizer phase decides (as ref is not usd) to use an index for GROUP BY,
      which has bad performance.
      
      Description of fix:
      - All new code is protected by the "optimizer_adjust_secondary_key_costs"
        variable, which is now a bit map, and is only executed if the option
        "disable_forced_index_in_group_by" set.
      - Corrects GROUP BY handling in test_if_cheaper_ordering() by making
        the choise of using and index with GROUP BY cost based instead of rule
        based.
      - Adds TIME_FOR_COMPARE to all costs, when using group by, to make
        read_time, index_scan_time and range_cost comparable.
      
      Other things:
      - Made optimizer_adjust_secondary_key_costs a bit map (compatible with old
        code).
      
      Notes:
      Current code ignores costs for the algorithm used when doing GROUP
      BY on the first table:
        - Create an in-memory temporary table for handling group by and doing a
          filesort of the result file
      We can probably in 10.6 continue to ignore this cost.
      
      This patch should NOT be merged to 11.0 series (not needed in 11.0).
      3907345e
    • Monty's avatar
      Fixed some compiler warnings · 4106974b
      Monty authored
      4106974b
    • Brandon Nesterenko's avatar
      MDEV-29369: rpl.rpl_semi_sync_shutdown_await_ack fails regularly with Result content mismatch · 03d1346e
      Brandon Nesterenko authored
      This test was prone to failures for a few reasons, summarized below:
      
       1) MDEV-32168 introduced “only_running_threads=1” to
      slave_stop.inc, which allowed the stop logic to bypass an
      attempting-to-reconnect IO thread. That is, the IO thread could
      realize the master shutdown in `read_event()`, and thereby call into
      `try_to_reconnect()`. This would leave the IO thread up when the
      test expected it to be stopped. Fixed by explicitly stopping the
      IO thread and allowing an error state, as the above case would
      lead to errno 2003.
      
       2) On slow systems (or those running profiling tools, e.g. MSAN),
      the waiting-for-ack transaction can complete before the system
      processes the `SHUTDOWN WAIT FOR ALL SLAVES`. There was shutdown
      preparation logic in-between the transaction and shutdown itself,
      which contributes to this problem. This patch also moves this
      preparation logic before the transaction, so there is less to do
      in-between the calls.
      
       3) Changed work-around for MDEV-28141 to use debug_sync instead
      of sleep delay, as it was still possible to hit the bug on very
      slow systems.
      
       4) Masked MTR variable reset with disable/enable query log
      
      Reviewed By:
      ============
      Kristian Nielsen <knielsen@knielsen-hq.org>
      03d1346e
    • Brandon Nesterenko's avatar
      MDEV-14357: rpl.rpl_domain_id_filter_io_crash failed in buildbot with wrong result · ee895583
      Brandon Nesterenko authored
      A race condition with the SQL thread, where depending on if it was
      killed before or after it had executed the fake/generated IGN_GTIDS
      Gtid_list_log_event, may or may not update gtid_slave_pos with the
      position of the ignored events. Then, the slave would be restarted
      while resetting IGNORE_DOMAIN_IDS to be empty, which would result in
      the slave requesting different starting locations, depending on
      whether or not gtid_slave_pos was updated. And, because previously
      ignored events could now be requested and executed (no longer
      ignored), their presence would fail the test.
      
      This patch fixes this in two ways. First, to use GTID positions for
      synchronization rather than binlog file positions. Then second, to
      synchronize the SQL thread’s gtid_slave_pos with the ignored events
      before killing the SQL thread.
      
      To consistently reproduce the test failure, the following patch can
      be applied:
      
      diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
      index f51f5b7deec..de62233acff 100644
      --- a/sql/log_event_server.cc
      +++ b/sql/log_event_server.cc
      @@ -3686,6 +3686,12 @@ Gtid_list_log_event::do_apply_event(rpl_group_info *rgi)
           void *hton= NULL;
           uint32 i;
      
      +    sleep(1);
      +    if (rli->sql_driver_thd->killed || rli->abort_slave)
      +    {
      +      return 0;
      +    }
      +
      
      Reviewed By:
      ============
      Kristian Nielsen <knielsen@knielsen-hq.org>
      ee895583
    • Oleksandr Byelkin's avatar