Skip to content

Commit

Permalink
v2.20
Browse files Browse the repository at this point in the history
Former-commit-id: a9a5385df1fe576c89a5a3d0bc39ae2207f849a5 [formerly cfc7175ab3e87358f028b022315eeccaf64184a9] [formerly 30ad470db93301fad6f2a667accba220f20223eb [formerly 9f47d1a59bcb23e9b074968dde31ce75afa6497c]]
Former-commit-id: a1b0610dd1cce337b682314e85f5f3976b1873b1 [formerly fbe1d2f4bb405b7dcb34f0a3757db8b307afff42]
Former-commit-id: e835167398bc18970028afcb36c526d893d4f8d3
Former-commit-id: 809cc95258ea0a1b558c9699fde9b2925d219c94
  • Loading branch information
Bob Simons committed Sep 30, 2022
1 parent f56c24d commit 54a0239
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 50 deletions.
4 changes: 2 additions & 2 deletions WEB-INF/classes/com/cohort/util/Math2.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class Math2 {
public static long maxSafeMemory = maxMemory * 3L / 4; //75% the max we should consider getting to
public static long dangerousMemory = maxMemory * 9L / 10; //90% this is really bad

public static long alwaysOkayMemoryRequest = maxSafeMemory / 20;
public static long alwaysOkayMemoryRequest = maxSafeMemory / 40;

/**
* These are *not* final so EDStatic can replace them with translated Strings.
Expand Down Expand Up @@ -468,7 +468,7 @@ public static void ensureMemoryAvailable(final long nBytes, final String attribu
// even if it was for ERDDAP management (i.e., shooting myself in the foot).

//this is a little risky, but avoids frequent calls to calculate memoryInUse
if (nBytes < alwaysOkayMemoryRequest) //e.g., 8GB -&gt; maxSafe=6GB /20=300MB
if (nBytes < alwaysOkayMemoryRequest) //e.g., 8GB -&gt; maxSafe=6GB /40=150MB
return;

//is this single request by itself too big under any circumstances?
Expand Down
4 changes: 3 additions & 1 deletion WEB-INF/classes/gov/noaa/pfel/erddap/Erddap.java
Original file line number Diff line number Diff line change
Expand Up @@ -3610,7 +3610,9 @@ public void doStatus(int language, HttpServletRequest request, HttpServletRespon
int po = traces.indexOf('\n');
if (po > 0)
sb.append(traces.substring(0, po + 1));
sb.append(EDStatic.gcCalled + " gc calls and " + EDStatic.requestsShed + " requests shed since last major LoadDatasets\n");
sb.append(EDStatic.gcCalled + " gc calls, " +
EDStatic.requestsShed + " requests shed, and " +
EDStatic.dangerousMemoryEmails + " dangerousMemoryEmails since last major LoadDatasets\n");
sb.append(Math2.memoryString() + " " + Math2.xmxMemoryString() + "\n\n");

EDStatic.addCommonStatistics(sb);
Expand Down
9 changes: 7 additions & 2 deletions WEB-INF/classes/gov/noaa/pfel/erddap/LoadDatasets.java
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,7 @@ public void run() {
//reset since last majorReload
EDStatic.gcCalled = 0;
EDStatic.requestsShed = 0;
EDStatic.dangerousMemoryEmails = 0;
EDStatic.dangerousMemoryFailures = 0;
EDStatic.tooManyRequests = 0;

Expand All @@ -1077,7 +1078,9 @@ public void run() {
if (threadSummary != null)
contentSB.append(threadSummary + "\n");

contentSB.append(EDStatic.gcCalled + " gc calls and " + EDStatic.requestsShed + " requests shed since last major LoadDatasets\n");
contentSB.append(EDStatic.gcCalled + " gc calls, " +
EDStatic.requestsShed + " requests shed, and " +
EDStatic.dangerousMemoryEmails + " dangerousMemoryEmails since last major LoadDatasets\n");
contentSB.append(Math2.memoryString() + " " + Math2.xmxMemoryString() + "\n\n");
contentSB.append(stars + "\nTallied Usage Information\n\n");
contentSB.append(EDStatic.tally.toString(50));
Expand Down Expand Up @@ -1215,7 +1218,9 @@ public void run() {
if (threadSummary != null)
sb.append(threadSummary + "\n");

sb.append(EDStatic.gcCalled + " gc calls and " + EDStatic.requestsShed + " requests shed since last major LoadDatasets\n");
sb.append(EDStatic.gcCalled + " gc calls, " +
EDStatic.requestsShed + " requests shed, and " +
EDStatic.dangerousMemoryEmails + " dangerousMemoryEmails since last major LoadDatasets\n");
sb.append(Math2.memoryString() + " " + Math2.xmxMemoryString() + "\n\n");
EDStatic.addCommonStatistics(sb);
sb.append(EDStatic.tally.toString("Large Request, IP address (since last Major LoadDatasets)", 50));
Expand Down
42 changes: 22 additions & 20 deletions WEB-INF/classes/gov/noaa/pfel/erddap/util/EDStatic.java
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public class EDStatic {
* <br>2.17 released on 2022-02-16
* <br>2.18 released on 2022-02-23
* <br>2.19 released on 2022-09-10
* <br>2.20 released on 2022-09-??
* <br>2.20 released on 2022-09-30
*
* For master branch releases, this will be a floating point
* number with 2 decimal digits, with no additional text.
Expand Down Expand Up @@ -265,6 +265,7 @@ public class EDStatic {
public static int touchThreadSucceededDistributionTotal[]= new int[String2.TimeDistributionSize];
public static volatile int gcCalled = 0; //since last Major LoadDatasets
public static volatile int requestsShed = 0; //since last Major LoadDatasets
public static volatile int dangerousMemoryEmails = 0; //since last Major LoadDatasets
public static volatile int dangerousMemoryFailures = 0; //since last Major LoadDatasets
public static StringBuffer suggestAddFillValueCSV = new StringBuffer(); //EDV constructors append message here //thread-safe but probably doesn't need to be

Expand All @@ -288,12 +289,12 @@ public class EDStatic {
public final static String ipAddressUnknown = "(unknownIPAddress)";
public final static ConcurrentHashMap<String,IntArray> ipAddressQueue = new ConcurrentHashMap(); //ipAddress -> list of request#
public final static int DEFAULT_ipAddressMaxRequestsActive = 2; //in datasets.xml
public final static int DEFAULT_ipAddressMaxRequests = 7; //in datasets.xml //more requests will see Too Many Requests error. This must be at least 6 because browsers make up to 6 simultaneous requests. This can't be >1000.
public final static int DEFAULT_ipAddressMaxRequests = 15; //in datasets.xml //more requests will see Too Many Requests error. This must be at least 6 because browsers make up to 6 simultaneous requests. This can't be >1000.
public final static String DEFAULT_ipAddressUnlimited = ", " + ipAddressUnknown;
public static int ipAddressMaxRequestsActive = DEFAULT_ipAddressMaxRequestsActive; //in datasets.xml
public static int ipAddressMaxRequests = DEFAULT_ipAddressMaxRequests; //in datasets.xml //more requests will see Too Many Requests error. This must be at least 6 because browsers make up to 6 simultaneous requests.
public static HashSet<String> ipAddressUnlimited = //in datasets.xml //read only. New one is swapped into place. You can add and remove addresses as needed.
new HashSet<String>(String2.toArrayList(StringArray.fromCSVNoBlanks(EDStatic.DEFAULT_ipAddressUnlimited).toArray()));
new HashSet<String>(String2.toArrayList(StringArray.fromCSVNoBlanks(DEFAULT_ipAddressUnlimited).toArray()));
public static int tooManyRequests = 0; //nRequests exceeding ipAddressMaxRequests, since last major datasets reload
public final static String translationDisclaimer =
//from https://cloud.google.com/translate/attribution
Expand Down Expand Up @@ -2514,7 +2515,7 @@ else if ((upo != -1 && upo != 4) ||
convertUnitsNotesAr = getNotNothingString(messagesAr, "convertUnitsNotes", errorInMethod);
for (int tl = 0; tl < nLanguages; tl++)
convertUnitsNotesAr[tl] = convertUnitsNotesAr[tl]
.replace("&unitsStandard;", EDStatic.units_standard);
.replace("&unitsStandard;", units_standard);
convertUnitsServiceAr = getNotNothingString(messagesAr, "convertUnitsService", errorInMethod);
convertURLsAr = getNotNothingString(messagesAr, "convertURLs", errorInMethod);
convertURLsIntroAr = getNotNothingString(messagesAr, "convertURLsIntro", errorInMethod);
Expand Down Expand Up @@ -3497,7 +3498,7 @@ else if ((upo != -1 && upo != 4) ||

WMSNotesAr = getNotNothingString(messagesAr, "WMSNotes", errorInMethod);
for (int tl = 0; tl < nLanguages; tl++)
EDStatic.WMSNotesAr[tl] = EDStatic.WMSNotesAr[tl].replace( "&WMSSEPARATOR;", Character.toString(EDD.WMS_SEPARATOR));
WMSNotesAr[tl] = WMSNotesAr[tl].replace( "&WMSSEPARATOR;", Character.toString(EDD.WMS_SEPARATOR));

yourEmailAddressAr = getNotNothingString(messagesAr, "yourEmailAddress", errorInMethod);
zoomInAr = getNotNothingString(messagesAr, "zoomIn", errorInMethod);
Expand Down Expand Up @@ -4677,8 +4678,8 @@ public static void addCommonStatistics(StringBuilder sb) {
sb.append(String2.getTimeDistributionStatistics(touchThreadSucceededDistributionTotal)); sb.append('\n');
sb.append('\n');

sb.append(EDStatic.tally.toString("Language (since last daily report)", 50)); //added v2.15
sb.append(EDStatic.tally.toString("Language (since startup)", 50));
sb.append(tally.toString("Language (since last daily report)", 50)); //added v2.15
sb.append(tally.toString("Language (since startup)", 50));

sb.append(SgtMap.topographyStats() + "\n");
sb.append(GSHHS.statsString() + "\n");
Expand Down Expand Up @@ -4956,15 +4957,15 @@ public static void sendHttpUnauthorizedError(int language, int requestNumber, St
if (datasetID != null && datasetID.length() > 0)
message = MessageFormat.format(
graphsAccessibleToPublic?
EDStatic.notAuthorizedForDataAr[language] :
EDStatic.notAuthorizedAr[language],
notAuthorizedForDataAr[language] :
notAuthorizedAr[language],
loggedInAsHttps.equals(loggedInAs)? "" : loggedInAs,
datasetID);

lowSendError(requestNumber, response, HttpServletResponse.SC_UNAUTHORIZED, message);

} catch (Throwable t2) {
EDStatic.rethrowClientAbortException(t2); //first thing in catch{}
rethrowClientAbortException(t2); //first thing in catch{}
String2.log("Error in sendHttpUnauthorizedError for request #" + requestNumber + ":\n" +
(message == null? "" : message + "\n") +
MustBe.throwableToString(t2));
Expand Down Expand Up @@ -5984,7 +5985,7 @@ public static String passThroughJsonpQuery(int language, HttpServletRequest requ
return "";
String functionName = jsonp.substring(7); //it will be because it starts with .jsonp=
if (!String2.isJsonpNameSafe(functionName))
throw new SimpleException(EDStatic.bilingual(language,
throw new SimpleException(bilingual(language,
errorJsonpFunctionNameAr[0],
errorJsonpFunctionNameAr[language]));
return ".jsonp=" + SSR.minimalPercentEncode(functionName) + "&";
Expand Down Expand Up @@ -6152,7 +6153,7 @@ public static String nMatchingDatasetsHtml(int language, int nMatches, int page,
"...\n");
if (page >= 3) sb.append(
url0 + (page>2? prev : bmrk) + url1 + (page - 1) + url2 + (page - 1) + url3);
sb.append("&nbsp;" + page + "&nbsp;(" + EDStatic.nMatchingCurrentAr[language] + ")&nbsp;\n"); //always show current page
sb.append("&nbsp;" + page + "&nbsp;(" + nMatchingCurrentAr[language] + ")&nbsp;\n"); //always show current page
if (page <= lastPage - 2) sb.append(
url0 + (page<lastPage-1? next : bmrk) + url1 + (page + 1) + url2 + (page + 1) + url3);
if (page <= lastPage - 3) sb.append(
Expand Down Expand Up @@ -6438,6 +6439,7 @@ public static boolean shedThisRequest(int language, int requestNumber, HttpServl
//if memory use is dangerously high and I haven't reported this incident, report it
if (inUse >= Math2.dangerousMemory && lastActiveRequestReportTime == 0) {
lastActiveRequestReportTime = System.currentTimeMillis(); //do first so other threads don't also report this
dangerousMemoryEmails++;
activeRequests.remove(requestNumber + ""); //don't blame this request
String activeRequestLines[] = activeRequests.values().toArray(new String[0]);
Arrays.sort(activeRequestLines);
Expand All @@ -6449,7 +6451,7 @@ public static boolean shedThisRequest(int language, int requestNumber, HttpServl
"Active requests:\n" +
String2.toNewlineString(activeRequestLines);
String2.log(report);
email(EDStatic.emailEverythingToCsv, "Dangerously High Memory Use!!!", report);
email(emailEverythingToCsv, "Dangerously High Memory Use!!!", report);
}

//memory use is too high, so shed this request
Expand Down Expand Up @@ -6577,7 +6579,7 @@ public static void sendError(int requestNumber, HttpServletRequest request,

} else if (tError.indexOf(Math2.memoryArraySize.substring(0, 25)) >= 0) {
errorNo = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE; //http error 413 (the old name for Payload Too Large), although it could be other user's requests that are too large
String ipAddress = EDStatic.getIPAddress(request);
String ipAddress = getIPAddress(request);
tally.add("OutOfMemory (Array Size), IP Address (since last Major LoadDatasets)", ipAddress);
tally.add("OutOfMemory (Array Size), IP Address (since last daily report)", ipAddress);
tally.add("OutOfMemory (Array Size), IP Address (since startup)", ipAddress);
Expand All @@ -6586,15 +6588,15 @@ public static void sendError(int requestNumber, HttpServletRequest request,
tError.indexOf(Math2.memoryThanCurrentlySafe.substring(0, 25)) >= 0) { //!!! TROUBLE: but that matches memoryThanSafe (in English) too!
errorNo = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE; //http error 413 (the old name for Payload Too Large), although it could be other user's requests that are too large
dangerousMemoryFailures++;
String ipAddress = EDStatic.getIPAddress(request);
String ipAddress = getIPAddress(request);
tally.add("OutOfMemory (Too Big), IP Address (since last Major LoadDatasets)", ipAddress);
tally.add("OutOfMemory (Too Big), IP Address (since last daily report)", ipAddress);
tally.add("OutOfMemory (Too Big), IP Address (since startup)", ipAddress);

} else if (tErrorLC.indexOf(Math2.memory) >= 0) {
//catchall for remaining memory problems
errorNo = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE; //http error 413 (the old name for Payload Too Large)
String ipAddress = EDStatic.getIPAddress(request);
String ipAddress = getIPAddress(request);
tally.add("OutOfMemory (Way Too Big), IP Address (since last Major LoadDatasets)", ipAddress);
tally.add("OutOfMemory (Way Too Big), IP Address (since last daily report)", ipAddress);
tally.add("OutOfMemory (Way Too Big), IP Address (since startup)", ipAddress);
Expand Down Expand Up @@ -6658,8 +6660,8 @@ public static void lowSendError(int requestNumber, HttpServletResponse response,
//because any of these errors could be in a script
//and it's good to slow the script down (prevent 100 bad requests/second)
//and if it's a human they won't even notice a short delay
if (EDStatic.slowDownTroubleMillis > 0)
Math2.sleep(EDStatic.slowDownTroubleMillis);
if (slowDownTroubleMillis > 0)
Math2.sleep(slowDownTroubleMillis);

//put the HTTP status code name at the start of the message (from Wikipedia list
// https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
Expand Down Expand Up @@ -6743,7 +6745,7 @@ public static void testUpdateUrls() throws Exception {
add.set( "b", "http://www.whoi.edu"); //purposely out-of-date
add.set( "ten", 10.0);
add.set( "sourceUrl", "http://coastwatch.pfel.noaa.gov"); //purposely out-of-date
EDStatic.updateUrls(source, add);
updateUrls(source, add);
String results = add.toString();
String expected =
" a=https://coastwatch.pfeg.noaa.gov\n" +
Expand All @@ -6758,7 +6760,7 @@ public static void testUpdateUrls() throws Exception {
add.set("b", "http://www.whoi.edu");
add.set("nine", 9.0);
add.set("sourceUrl", "http://coastwatch.pfel.noaa.gov");
EDStatic.updateUrls(null, add);
updateUrls(null, add);
results = add.toString();
expected =
" a=https://coastwatch.pfeg.noaa.gov\n" +
Expand Down
Loading

0 comments on commit 54a0239

Please sign in to comment.