Index: main/trunk/greenstone2/runtime-src/src/colservr/browsefilter.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/colservr/browsefilter.cpp	(revision 31902)
+++ main/trunk/greenstone2/runtime-src/src/colservr/browsefilter.cpp	(revision 31903)
@@ -143,6 +143,6 @@
     if(parentnode == "oai") { // doing an OAI listidentifiers request
 
-      // open up the oai-inf db, if it exists, and return all IDs
-      // if it doesn't exist, proceed as usual
+      // open up the oai-inf db if it exists, and return all IDs *except* the special OID=OAI_EARLIESTTIMESTAMP_OID
+      // if oai-inf db doesn't exist, proceed as usual
       success = get_oaiinf_db_entries(response, err, logout); //adds any stuff in oai-inf db for the current OID to resultdoc.metadata
 
@@ -377,5 +377,13 @@
     
     resultdoc.OID = (*key_here);
-   
+    
+    // OAI_EARLIESTTIMESTAMP_OID is the OID of a special record that we'll ignore
+    // here in browsefilter.cpp, since it's not a doc.
+    // When the *metadata* for this special OID is requested, source.cpp will handle it
+    if(resultdoc.OID == OAI_EARLIESTTIMESTAMP_OID) {
+      ++key_here;
+      continue;
+    }
+
     if(!oaidb_ptr->getinfo(resultdoc.OID, oai_info)) {
       logout << text_t2ascii
Index: main/trunk/greenstone2/runtime-src/src/colservr/collectserver.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/colservr/collectserver.cpp	(revision 31902)
+++ main/trunk/greenstone2/runtime-src/src/colservr/collectserver.cpp	(revision 31903)
@@ -535,5 +535,5 @@
 	  // first check for oai metadata from the oai_db, if asked for it (if FROAI is set)
 	  if(((*source_here).s != NULL) &&
-	     request.filterResultOptions & FROAI &&
+	     (request.filterResultOptions & FROAI) &&
 	     ((*source_here).s->get_oai_metadata(request.requestParams, request.refParams,
 						 request.getParents, request.fields, 
@@ -546,4 +546,14 @@
 	  }
 
+	  // if OID is the special OAI specific OAI_EARLIESTTIMESTAMP_OID,
+	  // then we'd have got its OAI meta above if we were requested to do so.
+	  // Either way, we won't be additionally getting regular meta for this OID,
+	  // as it's not a real doc OID, so we stop processing this OID here.
+	  if((*resultdoc_here).OID == OAI_EARLIESTTIMESTAMP_OID) {
+	    ++source_here;
+	    if(processed == true) break;
+	    else continue;
+	  }
+  
 	  // We may or may not have got oai_meta (depends on if FROAI was set).
 	  // If we didn't get oai_meta, then deleted_status would still be "".
Index: main/trunk/greenstone2/runtime-src/src/colservr/comtypes.h
===================================================================
--- main/trunk/greenstone2/runtime-src/src/colservr/comtypes.h	(revision 31902)
+++ main/trunk/greenstone2/runtime-src/src/colservr/comtypes.h	(revision 31903)
@@ -48,4 +48,7 @@
 #endif
 
+
+const text_t OAI_EARLIESTTIMESTAMP_OID = "earliesttimestamp";
+         // https://www.tutorialspoint.com/cplusplus/cpp_constants_literals.htm
 
 enum comerror_t {noError, authenticationFailure, protocolError, 
@@ -113,4 +116,12 @@
   text_tmap      dynamic_classifiers;
   text_t		 earliestDatestamp;	  // For OAIserver validation. Time since linux Epoch, expressed as (long) integer value in string form
+  // This field stored the builddate value from a collection's index/build.cfg file.
+  // This field earliestDatestamp was used when oaiaction.calcEarliestDatestamp() needed to
+  // determine the earliest timestamp of the repository, by selecting the earliestDatestamp among
+  // all oai collections. Now it's no longer used by OAI, as that resorts to consulting oai-inf.db
+  // of each collection, which has a collection's earliest timestamp stored, to work out the
+  // earliest timestamp among all collections. But the build.cfg builddate stored in the
+  // earliestDatestamp field may still be useful in future for some purpose, so leaving it alone.
+  
 };
 
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/listidsaction.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/listidsaction.cpp	(revision 31902)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/listidsaction.cpp	(revision 31903)
@@ -237,4 +237,6 @@
   text_tset        metadata;
   ofstream         logout("oai.log", ios::app);
+    // logout closed automatically by object destructor at this method's end:
+    // https://stackoverflow.com/questions/748014/do-i-need-to-manually-close-an-ifstream
   text_t           lastModified = "";
   text_t           deleted_status = "";
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.cpp	(revision 31902)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.cpp	(revision 31903)
@@ -551,4 +551,11 @@
 }
 
+// works out the earliest date/timestamp of the OAI repository,
+// which compares and then selects the earliest timestamp value among all collections.
+// In the past, the earliest date/timestamp used to be the unix epoch,
+// later it became the earliest among each collection's builddate in build.cfg,
+// and now, after implementing the OAI deletion policy, it needed to become the earliest
+// among each collection's OAI_EARLIESTTIMESTAMP_OID record's timestamp value.
+
 text_t oaiaction::calcEarliestDatestamp(recptproto *protocol, oaiargs &params) {
 	
@@ -570,6 +577,9 @@
 	// (the earliestDatestamp for a collection has already been extracted from 
 	// their build.cfg file at this point by collectserver::configure. The field
-	// is declared in comtypes.h) 	
-	
+	// is declared in comtypes.h)
+	
+	// We've changed this again to grab the timestamp field of the OAI_EARLIESTTIMESTAMP_OID
+	// record of each collection's oai-inf.db (representing the time that collection was
+	// built for the very first time) and choosing the earliest among all of them.
 	
 	// Get a list of the OAI-enabled collections available
@@ -597,4 +607,6 @@
 			collection_iterator++;
 		}
+
+		ofstream         logout("oai.log", ios::app);
 		
 		// Now loop through the remaining collections
@@ -604,4 +616,25 @@
 			collection_name = (*collection_iterator);
 			
+			text_tset        metadata;
+			FilterResponse_t response;
+
+			// get timestamps from etc/oai-inf.<db> now, no longer from build.cfg
+			// request the special record with OID=OAI_EARLIESTTIMESTAMP_OID for the collection
+			bool status_ok = get_oai_info(OAI_EARLIESTTIMESTAMP_OID, collection_name, "", metadata, false, protocol, response, logout);
+			
+			if(status_ok) {
+			  ResultDocInfo_t doc_info = response.docInfo[0];
+			  text_t collEarliestTimestamp;
+			  // the timestamp we want lives in the "lastmodified" field of the OAI_EARLIESTTIMESTAMP_OID record
+			  this->getLastModifiedDate(doc_info, collEarliestTimestamp);
+			  
+			  if(earliestDatestamp == "") { // first earliestdatestamp we've seen for an oai collection
+			    earliestDatestamp = collEarliestTimestamp;
+			  } else if(collEarliestTimestamp < earliestDatestamp) {
+			    earliestDatestamp = collEarliestTimestamp;
+			  }
+			} /*else { // collection may not have oai-inf.db (yet), check build.cfg?
+			    // No: no need to use the old way as fallback
+			   
 			ColInfoResponse_t cinfo;
 			comerror_t err;	
@@ -618,7 +651,10 @@
 				}
 			}
+		      }
+		      */
 			collection_iterator++;
 			
-		}		
+		}
+		logout.close();
 	}
 		
Index: main/trunk/greenstone2/runtime-src/src/protocol/recptprototools.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/protocol/recptprototools.cpp	(revision 31902)
+++ main/trunk/greenstone2/runtime-src/src/protocol/recptprototools.cpp	(revision 31903)
@@ -34,4 +34,5 @@
 // THIS FILE IS A CANDIDATE FOR REFACTORING: merge get_info methods
 
+// overloaded, to allow "custom" filter options.
 bool get_info (const text_t &OID, const text_t &collection, const text_t &lang,
 	       const text_tset &metadata, bool getParents,
@@ -76,5 +77,4 @@
 }
 
-// overloaded, to allow "custom" filter options.
 bool get_info (const text_t &OID, const text_t &collection, const text_t &lang,
 	       const text_tset &metadata, const OptionValue_tarray &options,
