Index: main/trunk/greenstone2/runtime-src/src/oaiservr/identifyaction.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/identifyaction.cpp	(revision 24286)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/identifyaction.cpp	(revision 24412)
@@ -113,62 +113,8 @@
 	// their build.cfg file at this point by collectserver::configure. The field
 	// is declared in comtypes.h) 	
-	text_t earliestDatestamp = ""; // do not set default to unix epoch time "1970-01-01" yet
 	
-	// Get a list of the OAI-enabled collections available
-	text_tarray& collections = this->configuration->getCollectionsList();
-	if (collections.size() > 0)
-	{		
-		// get the identifier from the params
-		text_t identifier = params["identifier"];
-		text_t oai_OID_prefix = "oai:"+this->configuration->getRepositoryId()+":";
-		identifier.replace(oai_OID_prefix, "");
-
-		// Get the current collection from the identifier
-		text_t collection_name = "";
-		oaiclassifier::toGSDL(collection_name, identifier);
-
-		// Find the starting collection
-		text_tarray::iterator collection_iterator = collections.begin();
-		while (collection_iterator != collections.end())
-		{
-			if (collection_name == "" || collection_name == *collection_iterator)
-			{
-			  break;
-			}
-
-			collection_iterator++;
-		}
-		
-		// Now loop through the remaining collections
-		// to work out the earliest datestamp
-		while (collection_iterator != collections.end())
-		{
-			collection_name = (*collection_iterator);
-			
-			ColInfoResponse_t cinfo;
-			comerror_t err;	
-			protocol->get_collectinfo(collection_name, cinfo, err, cerr);
-			if (err == noError) {				
-				text_t eDatestamp = cinfo.earliestDatestamp;
-				time_t raw_time = (time_t)eDatestamp.getint();
-				eDatestamp = this->parseDatestamp(raw_time);
-				
-				if(earliestDatestamp == "") { // first earliestdatestamp we've seen for an oai collection
-					earliestDatestamp = eDatestamp;
-				} else if(eDatestamp < earliestDatestamp) {
-					earliestDatestamp = eDatestamp;
-				}				
-			}
-			collection_iterator++;
-			
-		}		
-	}
+	this->calcEarliestDatestamp(protocol, params);	// force the calculation. Sets mEarliestDatestamp member variable
 	
-	// if repository's earliestDatestamp is still unset, default to unix epoch time
-	if(earliestDatestamp == "") { 
-		earliestDatestamp = "1970-01-01";
-	}	
-	
-    output << utf8convert << "  <earliestDatestamp>"<< earliestDatestamp <<"</earliestDatestamp>\n";
+    output << utf8convert << "  <earliestDatestamp>"<< this->mEarliestDatestamp <<"</earliestDatestamp>\n";
     output << utf8convert << "  <deletedRecord>no</deletedRecord>\n";
     output << utf8convert << "  <granularity>YYYY-MM-DD</granularity>\n";
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/listrecsaction.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/listrecsaction.cpp	(revision 24286)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/listrecsaction.cpp	(revision 24412)
@@ -156,5 +156,5 @@
       this->errorType = "badArgument";
       return false;
-    }
+    }	
   }
 
@@ -178,5 +178,5 @@
       return false;
     }
-
+	
     // Check the collection is one that is in the list in the oai.cfg file
     text_tarray &collections = this->configuration->getCollectionsList();
@@ -204,5 +204,36 @@
       return false;
     }
-  }
+	
+	// check we're not requested to retrieve records of *this* set/coll 
+	// from an earlier date than *this* set's earliestdatestamp
+	if (params["until"] != "") {
+		text_t eDatestamp = cinfo.earliestDatestamp;
+		time_t raw_time = (time_t)eDatestamp.getint();
+		eDatestamp = this->parseDatestamp(raw_time);
+		
+		// error if request is for records of an earlier date than this coll/set's earliestDatestamp		
+		if(params["until"] < eDatestamp) { 
+			this->errorType = "noRecordsMatch"; // for *this* set/coll of the repository
+			return false;
+		}
+	}
+	
+  } else { // no set (collection) specified
+	 if (params ["until"] != "") { 	// check we're not requested to retrieve records of an earlier
+									// date than the earliestdatestamp across all collections/sets
+		// John Thompson advises not to do lazy evaluation of earliestDatestamp here, because 
+		// reading x number of build.cfg files for x number of collections to work out the 
+		// earliestDatestamp among them is not too expensive an operation, but we do want the OAI 
+		// Server to give accurate results when queried, as that's specified by the OAI protocol.
+		//if(this->mEarliestDatestamp == "") {
+		text_t eDatestamp = this->calcEarliestDatestamp(protocol, params);
+		//}
+		
+		if(params["until"] < eDatestamp) { // request is for records of an earlier date than earliestDatestamp		
+			this->errorType = "noRecordsMatch";
+			return false;
+		}		
+	 }
+  }	
 
   // If we've reached here everything must be fine
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.cpp	(revision 24286)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.cpp	(revision 24412)
@@ -41,5 +41,4 @@
 #include <time.h>
 
-
 oaiaction::oaiaction(const text_t &name)
 {
@@ -47,4 +46,5 @@
   this->configuration = NULL;
   this->name = name;
+  this->mEarliestDatestamp = "";
 }
 
@@ -491,2 +491,85 @@
     return false;
 }
+
+text_t oaiaction::calcEarliestDatestamp(recptproto *protocol, oaiargs &params) {
+	
+	text_t earliestDatestamp = ""; // do not set default to unix epoch time "1970-01-01" yet
+	
+	//text_t version = (this->configuration->getOAIVersion() <= 110) ? (text_t)"1.1":(text_t)"2.0";
+	//if(version == "2.0"){
+	
+	// earliestDatestamp *should* be the YYYY-MM-DD format of the oldest lastmodified record in the
+	// repository, but we're just setting it to be the default oldest possible date - ugly, but judged
+	// not to be worth the effort of trolling through all the lastmodified dates (by others with more 
+	// say than me)
+	
+	// The above was before. However, now we mirror GS3 way of dealing with 
+	// earliestDatestamp by going through the earliestDatestamp field of each OAI 
+	// collection's build.cfg in order to work out earliestdatestamp of this Repository:
+	// by going through all the collections and getting the earliest among the
+	// "earliestDatestamp" values stored for each collection in its build.cfg
+	// (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) 	
+	
+	
+	// Get a list of the OAI-enabled collections available
+	text_tarray& collections = this->configuration->getCollectionsList();
+	if (collections.size() > 0)
+	{	
+		// get the identifier from the params
+		text_t identifier = params["identifier"];
+		text_t oai_OID_prefix = "oai:"+this->configuration->getRepositoryId()+":";
+		identifier.replace(oai_OID_prefix, "");
+
+		// Get the current collection from the identifier
+		text_t collection_name = "";
+		oaiclassifier::toGSDL(collection_name, identifier);
+
+		// Find the starting collection
+		text_tarray::iterator collection_iterator = collections.begin();
+		while (collection_iterator != collections.end())
+		{
+			if (collection_name == "" || collection_name == *collection_iterator)
+			{
+			  break;
+			}
+
+			collection_iterator++;
+		}
+		
+		// Now loop through the remaining collections
+		// to work out the earliest datestamp
+		while (collection_iterator != collections.end())
+		{
+			collection_name = (*collection_iterator);
+			
+			ColInfoResponse_t cinfo;
+			comerror_t err;	
+			protocol->get_collectinfo(collection_name, cinfo, err, cerr);
+			if (err == noError) {				
+				text_t eDatestamp = cinfo.earliestDatestamp;
+				time_t raw_time = (time_t)eDatestamp.getint();
+				eDatestamp = this->parseDatestamp(raw_time);
+				
+				if(earliestDatestamp == "") { // first earliestdatestamp we've seen for an oai collection
+					earliestDatestamp = eDatestamp;
+				} else if(eDatestamp < earliestDatestamp) {
+					earliestDatestamp = eDatestamp;
+				}
+			}
+			collection_iterator++;
+			
+		}		
+	}
+		
+	//}
+	
+	// if repository's earliestDatestamp is still unset, default to unix epoch time
+	if(earliestDatestamp == "") { 		
+		earliestDatestamp = "1970-01-01";
+	}
+	
+	this->mEarliestDatestamp = earliestDatestamp;
+	return mEarliestDatestamp;
+}
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.h
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.h	(revision 24286)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/oaiaction.h	(revision 24412)
@@ -49,7 +49,8 @@
  public:
   oaiaction(const text_t &name);
-
+  
   virtual void setConfiguration(oaiconfig *config) { this->configuration = config; }
   text_t getName();
+  virtual text_t calcEarliestDatestamp(recptproto *protocol, oaiargs &params);
   text_t parseDatestamp(time_t &rawtime);// Convert date from raw time_t format to the string YYYY-MM-DD
   void   getResponseDate(text_t &date);  // Get the response date in UTC (GMT) time, plus local offset
@@ -86,4 +87,5 @@
   text_t     errorType;
   ostream  * logout;
+  text_t	mEarliestDatestamp;
 };
 #endif
