From 02abe3590dfd67d8d0f0eb8cdcfb14e72b61e1f1 Mon Sep 17 00:00:00 2001
From: Howard Chu <hyc@symas.com>
Date: Thu, 7 Jan 2016 18:29:19 +0000
Subject: [PATCH] Use MDB_PREV_MULTIPLE

in get_global_output_indices
---
 src/blockchain_db/lmdb/db_lmdb.cpp | 51 +++++++++++++++++++++++-------
 1 file changed, 40 insertions(+), 11 deletions(-)

diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 56f4d4c08..b43d5742f 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -2475,22 +2475,51 @@ void BlockchainLMDB::get_output_global_indices(const uint64_t& amount, const std
         LOG_PRINT_L1("Index: " << index << " Elems: " << num_elems << " partial results found for get_output_tx_and_index");
         break;
       }
-      while (index >= curcount)
+      if (!curcount && index > num_elems/2)
       {
-        TIME_MEASURE_START(db1);
-        if (mdb_cursor_get(cur, &k, &v, curcount == 0 ? MDB_GET_MULTIPLE : MDB_NEXT_MULTIPLE) != 0)
+        mdb_cursor_get(cur, &k, &v, MDB_LAST_DUP);
+        mdb_cursor_get(cur, &k, &v, MDB_PREV);    /* kludge to unset C_EOF */
+        mdb_cursor_get(cur, &k, &v, MDB_NEXT);
+        mdb_cursor_get(cur, &k, &v, MDB_GET_MULTIPLE);
+
+        curcount = num_elems;
+        while(1)
         {
-          // allow partial results
-          result = false;
-          break;
+          TIME_MEASURE_START(db1);
+          int count = v.mv_size / sizeof(uint64_t);
+          curcount -= count;
+          if (curcount > index)
+          {
+            mdb_cursor_get(cur, &k, &v, MDB_PREV_MULTIPLE);
+          } else
+          {
+            blockstart = curcount;
+            curcount += count;
+            break;
+          }
+          TIME_MEASURE_FINISH(db1);
+          t_dbmul += db1;
         }
 
-        int count = v.mv_size / sizeof(uint64_t);
+      } else
+      {
+        while (index >= curcount)
+        {
+          TIME_MEASURE_START(db1);
+          if (mdb_cursor_get(cur, &k, &v, curcount == 0 ? MDB_GET_MULTIPLE : MDB_NEXT_MULTIPLE) != 0)
+          {
+            // allow partial results
+            result = false;
+            break;
+          }
 
-        blockstart = curcount;
-        curcount += count;
-        TIME_MEASURE_FINISH(db1);
-        t_dbmul += db1;
+          int count = v.mv_size / sizeof(uint64_t);
+
+          blockstart = curcount;
+          curcount += count;
+          TIME_MEASURE_FINISH(db1);
+          t_dbmul += db1;
+        }
       }
 
       LOG_PRINT_L3("Records returned: " << curcount << " Index: " << index);