001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.util;
017:
018: /**
019: * We need a way to record how heavily used the server is, and adjust our
020: * behavior to reduce the load on the server.
021: * @author Joe Walker [joe at getahead dot ltd dot uk]
022: */
023: public class HitMonitor {
024: /**
025: * Create a HitMonitor that records the number of hits in the last n
026: * milliseconds.
027: * @param seconds The number of seconds to record hits for
028: */
029: public HitMonitor(int seconds) {
030: hitLog = new long[seconds];
031: }
032:
033: /**
034: * A hit has happened, record some load on the server
035: */
036: public void recordHit() {
037: synchronized (hitLog) {
038: trimHitLog();
039: hitLog[0]++;
040: }
041: }
042:
043: /**
044: * How to detect the number of hits in the time period specified in the
045: * constructor.
046: * @return The hit count
047: */
048: public int getHitsInLastPeriod() {
049: synchronized (hitLog) {
050: trimHitLog();
051:
052: int count = 0;
053: for (long hit : hitLog) {
054: count += hit;
055: }
056:
057: return count;
058: }
059: }
060:
061: /**
062: * Remove all the hits that are no longer relevant.
063: * PERFORMANCE: There is probably a faster way to do this
064: */
065: private void trimHitLog() {
066: long now = getCurrentTimestamp();
067: long secondsPassedSinceLastHit = now - zeroTimestamp;
068: zeroTimestamp = now;
069:
070: if (secondsPassedSinceLastHit > 0) {
071: // Move the counts down
072: for (int i = hitLog.length - 1; i >= 0; i--) {
073: if (i >= secondsPassedSinceLastHit) {
074: hitLog[i] = hitLog[i
075: - (int) secondsPassedSinceLastHit];
076: } else {
077: hitLog[i] = 0;
078: }
079: }
080: }
081: }
082:
083: /**
084: * A timestamp is {@link System#currentTimeMillis()} divided by 1000
085: * @return The current timestamp
086: */
087: private static long getCurrentTimestamp() {
088: return System.currentTimeMillis() / 1000;
089: }
090:
091: /**
092: * What is the timestamp of the first element of the hitLog?
093: */
094: private long zeroTimestamp = getCurrentTimestamp();
095:
096: /**
097: * Our log of hits
098: */
099: private final long[] hitLog;
100: }
|