From 31463f1164530464e97f30f6dad27a21842f3b19 Mon Sep 17 00:00:00 2001
From: Sergei Petrunia <sergey@mariadb.com>
Date: Wed, 28 Feb 2024 16:01:48 +0300
Subject: [PATCH] MDEV-33502: part#4: Dont make redundant
 extra(HA_EXTRA_[NO]_KEYREAD) calls

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
---
 sql/ha_partition.cc | 52 +++++++++++++++++++++++++++++++++++++++------
 sql/ha_partition.h  |  4 ++++
 2 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 74805112823..5eebd94c268 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -9314,8 +9314,9 @@ int ha_partition::extra(enum ha_extra_function operation)
   switch (operation) {
     /* Category 1), used by most handlers */
   case HA_EXTRA_NO_KEYREAD:
-    DBUG_RETURN(loop_partitions(end_keyread_cb, NULL));
+    DBUG_RETURN(loop_read_partitions(end_keyread_cb, NULL));
   case HA_EXTRA_KEYREAD:
+    DBUG_RETURN(loop_read_partitions(extra_cb, &operation));
   case HA_EXTRA_FLUSH:
   case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE:
     DBUG_RETURN(loop_partitions(extra_cb, &operation));
@@ -9537,7 +9538,7 @@ int ha_partition::extra_opt(enum ha_extra_function operation, ulong arg)
   switch (operation)
   {
     case HA_EXTRA_KEYREAD:
-      DBUG_RETURN(loop_partitions(start_keyread_cb, &arg));
+      DBUG_RETURN(loop_read_partitions(start_keyread_cb, &arg));
     case HA_EXTRA_CACHE:
       prepare_extra_cache(arg);
       DBUG_RETURN(0);
@@ -9625,14 +9626,53 @@ int ha_partition::loop_extra_alter(enum ha_extra_function operation)
 */
 
 int ha_partition::loop_partitions(handler_callback callback, void *param)
+{
+  int result= loop_partitions_over_map(&m_part_info->lock_partitions,
+                                       callback, param);
+  /* Add all used partitions to be called in reset(). */
+  bitmap_union(&m_partitions_to_reset, &m_part_info->lock_partitions);
+  return result;
+}
+
+
+/*
+  Call callback(part, param) on read_partitions (the ones used by the query)
+*/
+
+int ha_partition::loop_read_partitions(handler_callback callback, void *param)
+{
+  /*
+    There is no need to record partitions on m_partitions_to_reset as 
+    read_partitions were opened, etc - they will be reset anyway.
+  */
+  return loop_partitions_over_map(&m_part_info->read_partitions, callback,
+                                  param);
+}
+
+
+/**
+  Call callback(part, param) on specified set of partitions
+   
+    @part_map                       The set of partitions to call callback for
+    @param callback                 a callback to call for each partition
+    @param param                    a void*-parameter passed to callback
+
+    @return Operation status
+      @retval >0                    Error code
+      @retval 0                     Success
+*/
+
+int ha_partition::loop_partitions_over_map(const MY_BITMAP *part_map,
+                                           handler_callback callback,
+                                           void *param)
 {
   int result= 0, tmp;
   uint i;
-  DBUG_ENTER("ha_partition::loop_partitions");
+  DBUG_ENTER("ha_partition::loop_partitions_over_map");
 
-  for (i= bitmap_get_first_set(&m_part_info->lock_partitions);
+  for (i= bitmap_get_first_set(part_map);
        i < m_tot_parts;
-       i= bitmap_get_next_set(&m_part_info->lock_partitions, i))
+       i= bitmap_get_next_set(part_map, i))
   {
     /*
       This can be called after an error in ha_open.
@@ -9642,8 +9682,6 @@ int ha_partition::loop_partitions(handler_callback callback, void *param)
         (tmp= callback(m_file[i], param)))
       result= tmp;
   }
-  /* Add all used partitions to be called in reset(). */
-  bitmap_union(&m_partitions_to_reset, &m_part_info->lock_partitions);
   DBUG_RETURN(result);
 }
 
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index b252b7304f0..1757a20d5b7 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -989,6 +989,10 @@ class ha_partition final :public handler
                                           handler *file, uint *n);
   static const uint NO_CURRENT_PART_ID= NOT_A_PARTITION_ID;
   int loop_partitions(handler_callback callback, void *param);
+  int loop_partitions_over_map(const MY_BITMAP *map,
+                               handler_callback callback,
+                               void *param);
+  int loop_read_partitions(handler_callback callback, void *param);
   int loop_extra_alter(enum ha_extra_function operations);
   void late_extra_cache(uint partition_id);
   void late_extra_no_cache(uint partition_id);
-- 
2.30.9