blob: 16046abc7eb06650a0e3f08e15f5b530075d0db8 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.consoleproxy;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
/**
*
* ConsoleProxyGCThread does house-keeping work for the process, it helps cleanup log files,
* recycle idle client sessions without front-end activities and report client stats to external
* management software
*/
public class ConsoleProxyGCThread extends Thread {
private static final Logger s_logger = Logger.getLogger(ConsoleProxyGCThread.class);
private final static int MAX_SESSION_IDLE_SECONDS = 180;
private final Map<String, ConsoleProxyClient> connMap;
private final Set<String> removedSessionsSet;
private long lastLogScan = 0;
public ConsoleProxyGCThread(Map<String, ConsoleProxyClient> connMap, Set<String> removedSet) {
this.connMap = connMap;
this.removedSessionsSet = removedSet;
}
private void cleanupLogging() {
if (lastLogScan != 0 && System.currentTimeMillis() - lastLogScan < 3600000)
return;
lastLogScan = System.currentTimeMillis();
File logDir = new File("./logs");
File files[] = logDir.listFiles();
if (files != null) {
for (File file : files) {
if (System.currentTimeMillis() - file.lastModified() >= 86400000L) {
try {
file.delete();
} catch (Throwable e) {
s_logger.info("[ignored]"
+ "failed to delete file: " + e.getLocalizedMessage());
}
}
}
}
}
@Override
public void run() {
boolean bReportLoad = false;
long lastReportTick = System.currentTimeMillis();
while (true) {
cleanupLogging();
bReportLoad = false;
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("connMap=%s, removedSessions=%s", connMap, removedSessionsSet));
}
Set<String> e = connMap.keySet();
Iterator<String> iterator = e.iterator();
while (iterator.hasNext()) {
String key;
ConsoleProxyClient client;
synchronized (connMap) {
key = iterator.next();
client = connMap.get(key);
}
long seconds_unused = (System.currentTimeMillis() - client.getClientLastFrontEndActivityTime()) / 1000;
if (seconds_unused < MAX_SESSION_IDLE_SECONDS) {
continue;
}
synchronized (connMap) {
connMap.remove(key);
bReportLoad = true;
}
// close the server connection
s_logger.info("Dropping " + client + " which has not been used for " + seconds_unused + " seconds");
client.closeClient();
}
if (bReportLoad || System.currentTimeMillis() - lastReportTick > 5000) {
// report load changes
ConsoleProxyClientStatsCollector collector = new ConsoleProxyClientStatsCollector(connMap);
collector.setRemovedSessions(new ArrayList<>(removedSessionsSet));
String loadInfo = collector.getStatsReport();
ConsoleProxy.reportLoadInfo(loadInfo);
lastReportTick = System.currentTimeMillis();
synchronized (removedSessionsSet) {
removedSessionsSet.clear();
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Report load change : " + loadInfo);
}
}
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
s_logger.debug("[ignored] Console proxy was interrupted during GC.");
}
}
}
}