0d8013682ea0c2dcedf8c8639d78b8736be92ba4
hiram
  Thu Nov 1 12:47:29 2018 -0700
adding dropLimit option refs #22355

diff --git src/hg/dbTrash/dbTrash.c src/hg/dbTrash/dbTrash.c
index 5685945..ac23d86 100644
--- src/hg/dbTrash/dbTrash.c
+++ src/hg/dbTrash/dbTrash.c
@@ -10,30 +10,32 @@
 #include "jksql.h"
 #include "hdb.h"
 #include "customTrack.h"
 
 
 void usage()
 /* Explain usage and exit. */
 {
 errAbort(
   "dbTrash - drop tables from a database older than specified N hours\n"
   "usage:\n"
   "   dbTrash -age=N [-drop] [-historyToo] [-db=<DB>] [-verbose=N]\n"
   "options:\n"
   "   -age=N - number of hours old to qualify for drop.  N can be a float.\n"
   "   -drop - actually drop the tables, default is merely to display tables.\n"
+  "   -dropLimit=N - ERROR out if number of tables to drop is greater than limit,\n"
+  "                - default is to drop all expired tables\n"
   "   -db=<DB> - Specify a database to work with, default is "
 	CUSTOM_TRASH ".\n"
   "   -historyToo - also consider the table called 'history' for deletion.\n"
   "               - default is to leave 'history' alone no matter how old.\n"
   "               - this applies to the table 'metaInfo' also.\n"
   "   -extFile    - check extFile for lines that reference files\n"
   "               - no longer in trash\n"
   "   -extDel     - delete lines in extFile that fail file check\n"
   "               - otherwise just verbose(2) lines that would be deleted\n"
   "   -topDir     - directory name to prepend to file names in extFile\n"
   "               - default is /usr/local/apache/trash\n"
   "               - file names in extFile are typically: \"../trash/ct/...\"\n"
   "   -tableStatus  - use 'show table status' to get size data, very inefficient\n"
   "   -delLostTable - delete tables that exist but are missing from metaInfo\n"
   "                 - this operation can be even slower than -tableStatus\n"
@@ -48,30 +50,31 @@
     {"extFile", OPTION_BOOLEAN},
     {"extDel", OPTION_BOOLEAN},
     {"drop", OPTION_BOOLEAN},
     {"db", OPTION_STRING},
     {"topDir", OPTION_STRING},
     {"tableStatus", OPTION_BOOLEAN},
     {"delLostTables", OPTION_BOOLEAN},
     {"historyToo", OPTION_BOOLEAN},
     {NULL, 0},
 };
 
 static double ageHours = 0.0;	/*	must be specified	*/
 static boolean drop = FALSE;		/*	optional	*/
 static char *db = CUSTOM_TRASH;		/*	optional	*/
 static boolean historyToo = FALSE;	/*	optional	*/
+static int dropLimit = 0;		/*	optional	*/
 
 static time_t timeNow = 0;
 static time_t dropTime = 0;
 
 static boolean extFileCheck = FALSE;
 static boolean extDel = FALSE;
 static boolean tableStatus = FALSE;
 static boolean delLostTable = FALSE;
 static char *topDir = "/usr/local/apache/trash";
 
 void checkExtFile(struct sqlConnection *conn)
 /* check extFile table for files that have been removed */
 {
 char query[256];
 struct sqlResult *sr;
@@ -336,30 +339,41 @@
 struct hashEl *elList = hashElListHash(expiredHash);
 struct hashEl *el;
 for (el = elList; el != NULL; el = el->next)
     {
     verbose(2,"%s exists in %s only\n", el->name, CT_META_INFO);
     if (drop)
 	ctTouchLastUse(conn, el->name, FALSE); /* removes metaInfo row */
     }
 
 if (drop)
     {
     char comment[256];
     if (expiredTableNames)
 	{
 	struct slName *el;
+	int toBeDropped = slCount(expiredTableNames);
+	if (dropLimit > 0)
+	    {
+		if (toBeDropped > dropLimit)
+		    {
+            errAbort("ERROR: expected drop table count: %d\n\tis larger"
+		" than the dropLimit: %d\n\twill not proceed with this drop.",
+		toBeDropped, dropLimit);
+		    }
+	    }
+
 	int droppedCount = 0;
 	/* customTrash DB user permissions do not have permissions to
  	 * drop tables.  Must use standard special user that has all
  	 * permissions.  If we are not using the standard user at this
  	 * point, then switch to it.
 	 */
 	if (sameWord(db,CUSTOM_TRASH))
 	    {
 	    sqlDisconnect(&conn);
 	    conn = sqlConnect(db);
 	    }
 	for (el = expiredTableNames; el != NULL; el = el->next)
 	    {
 	    verbose(2,"# drop %s\n", el->name);
 	    sqlDropTable(conn, el->name);
@@ -446,27 +460,33 @@
         tm->tm_hour, tm->tm_min, tm->tm_sec, (unsigned long)dropTime);
     }
 else
     {
     verbose(1,"ERROR: specified age %.f must be greater than 0.0\n", ageHours);
     usage();
     }
 drop = optionExists("drop");
 historyToo = optionExists("historyToo");
 db = optionVal("db",db);
 extFileCheck = optionExists("extFile");
 extDel = optionExists("extDel");
 tableStatus = optionExists("tableStatus");
 topDir = optionVal("topDir", topDir);
 verbose(2,"#	drop requested: %s\n", drop ? "TRUE" : "FALSE");
+if (0 == dropLimit)
+    {
+	verbose(2,"#	    drop limit: unlimited, drop all expired\n");
+    } else {
+	verbose(2,"#	    drop limit: %d\n", dropLimit);
+    }
 verbose(2,"#	    historyToo: %s\n", historyToo ? "TRUE" : "FALSE");
 verbose(2,"#	       extFile: %s\n", extFileCheck ? "TRUE" : "FALSE");
 verbose(2,"#	        extDel: %s\n", extDel ? "TRUE" : "FALSE");
 verbose(2,"#	   tableStatus: %s\n", tableStatus ? "TRUE" : "FALSE");
 verbose(2,"#	        topDir: %s\n", topDir);
 verbose(2,"#	database: %s\n", db);
 
 dbTrash(db);
 if (verboseLevel() > 1)
     printVmPeak();
 return 0;
 }