Added yp2::PlainFile class which reads Unix-style plain text files.
[metaproxy-moved-to-github.git] / src / filter_multi.cpp
index 03916ba..0b98de0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_multi.cpp,v 1.10 2006-01-18 14:36:15 adam Exp $
+/* $Id: filter_multi.cpp,v 1.12 2006-01-19 09:35:43 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -240,14 +240,9 @@ void yf::Multi::Frontend::multi_move(std::list<BackendPtr> &blist)
     g.join_all();
 }
 
-
 void yf::Multi::FrontendSet::round_robin(int start, int number,
                                          std::list<PresentJob> &jobs)
 {
-    int fetched = 0;
-    int p = 1;
-    bool eof = true;
-
     std::list<int> pos;
     std::list<int> inside_pos;
     std::list<BackendSet>::const_iterator bsit;
@@ -257,39 +252,85 @@ void yf::Multi::FrontendSet::round_robin(int start, int number,
         inside_pos.push_back(0);
     }
 
-    std::list<int>::iterator psit = pos.begin();
-    std::list<int>::iterator esit = inside_pos.begin();
-    bsit = m_backend_sets.begin();
-    while (fetched < number)
+    int p = 1;
+#if 1
+    // optimization step!
+    int omin = 0;
+    while(true)
     {
-        if (bsit == m_backend_sets.end())
+        int min = 0;
+        int no_left = 0;
+        // find min count for each set which is > omin
+        for (bsit = m_backend_sets.begin(); bsit != m_backend_sets.end(); bsit++)
         {
-            psit = pos.begin();
-            esit = inside_pos.begin();
-            bsit = m_backend_sets.begin();
-            if (eof)
-                break;
-            eof = true;
+            if (bsit->m_count > omin)
+            {
+                if (no_left == 0 || bsit->m_count < min)
+                    min = bsit->m_count;
+                no_left++;
+            }
         }
-        if (*psit <= bsit->m_count)
+        if (no_left == 0) // if nothing greater than omin, bail out.
+            break;
+        int skip = no_left * min;
+        if (p + skip > start)  // step gets us "into" present range?
         {
-            if (p >= start)
+            // Yes. skip until start.. Rounding off is deliberate!
+            min = (start-p) / no_left;
+            p += no_left * min;
+            
+            std::cout << "\nBREAK min=" << min << " no_left=" << no_left << "\n\n";
+            // update positions in each set..
+            std::list<int>::iterator psit = pos.begin();
+            for (psit = pos.begin(); psit != pos.end(); psit++)
+                *psit += min;
+            break;
+        }
+        // skip on each set.. before "present range"..
+        p = p + skip;
+        
+        std::cout << "\nSKIP min=" << min << " no_left=" << no_left << "\n\n";
+        
+        std::list<int>::iterator psit = pos.begin();
+        for (psit = pos.begin(); psit != pos.end(); psit++)
+            *psit += min;
+        
+        omin = min; // update so we consider next class (with higher count)
+    }
+#endif
+    int fetched = 0;
+    bool more = true;
+    while (more)
+    {
+        more = false;
+        std::list<int>::iterator psit = pos.begin();
+        std::list<int>::iterator esit = inside_pos.begin();
+        bsit = m_backend_sets.begin();
+
+        for (; bsit != m_backend_sets.end(); psit++,esit++,bsit++)
+        {
+            if (fetched >= number)
             {
-                PresentJob job;
-                job.m_backend = bsit->m_backend;
-                job.m_pos = *psit;
-                job.m_inside_pos = *esit;
-                jobs.push_back(job);
-                (*esit)++;
-                fetched++;
+                more = false;
+                break;
+            }
+            if (*psit <= bsit->m_count)
+            {
+                if (p >= start)
+                {
+                    PresentJob job;
+                    job.m_backend = bsit->m_backend;
+                    job.m_pos = *psit;
+                    job.m_inside_pos = *esit;
+                    jobs.push_back(job);
+                    (*esit)++;
+                    fetched++;
+                }
+                (*psit)++;
+                p++;
+                more = true;
             }
-            (*psit)++;
-            p++;
-            eof = false;
         }
-        psit++;
-        esit++;
-        bsit++;
     }
 }
 
@@ -766,7 +807,6 @@ Z_Entry *yf::Multi::ScanTermInfo::get_entry(ODR odr)
 void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req)
 {
     Z_ScanRequest *req = apdu_req->u.scanRequest;
-    int no_targets = 0;
 
     int default_num_db = req->num_databaseNames;
     char **default_db = req->databaseNames;
@@ -786,7 +826,6 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req)
         }
         p->request() = apdu_req;
         p->copy_filter(package);
-        no_targets++;
     }
     multi_move(m_backend_list);
 
@@ -873,7 +912,11 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req)
                     }
                 }
                 // after
-                for (i = position-1; i<num_entries; i++)
+                if (position <= 0)
+                    i = 0;
+                else
+                    i = position-1;
+                for ( ; i<num_entries; i++)
                 {
                     Z_Entry *ent = entries[i];
 
@@ -920,8 +963,7 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req)
         }
     }
 
-
-    if (false)
+    if (true)
     {
         std::cout << "BEFORE\n";
         ScanTermInfoList::iterator it = entries_before.begin();
@@ -953,24 +995,38 @@ void yf::Multi::Frontend::scan2(Package &package, Z_APDU *apdu_req)
         int number_returned = *req->numberOfTermsRequested;
         int position_returned = *req->preferredPositionInResponse;
         
-        resp->positionOfTerm = odr_intdup(odr, position_returned);
-        resp->numberOfEntriesReturned = odr_intdup(odr, number_returned);
-        
         resp->entries->num_entries = number_returned;
         resp->entries->entries = (Z_Entry**)
             odr_malloc(odr, sizeof(Z_Entry*) * number_returned);
         int i;
-        
+
+        int lbefore = entries_before.size();
+        if (lbefore < position_returned-1)
+            position_returned = lbefore+1;
+
         ScanTermInfoList::iterator it = entries_before.begin();
-        for (i = 0; i<position_returned-1; i++, it++)
+        for (i = 0; i<position_returned-1 && it != entries_before.end(); i++, it++)
         {
-            resp->entries->entries[i] = it->get_entry(odr);
+            resp->entries->entries[position_returned-2-i] = it->get_entry(odr);
         }
+
         it = entries_after.begin();
-        for (i = position_returned-1; i<number_returned; i++, it++)
+
+        if (position_returned <= 0)
+            i = 0;
+        else
+            i = position_returned-1;
+        for (; i<number_returned && it != entries_after.end(); i++, it++)
         {
             resp->entries->entries[i] = it->get_entry(odr);
         }
+
+        number_returned = i;
+
+        resp->positionOfTerm = odr_intdup(odr, position_returned);
+        resp->numberOfEntriesReturned = odr_intdup(odr, number_returned);
+        resp->entries->num_entries = number_returned;
+
         package.response() = f_apdu;
     }
 }