/* * Copyright 1999-2012 Alibaba Group. * * Licensed 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.alibaba.cobar.statistic; import java.util.Arrays; import java.util.concurrent.locks.ReentrantLock; /** * SQL统计排序记录器 * * @author xianmao.hexm 2010-9-30 上午10:48:28 */ public final class SQLRecorder { private int index; private long minValue; private final int count; private final int lastIndex; private final SQLRecord[] records; private final ReentrantLock lock; public SQLRecorder(int count) { this.count = count; this.lastIndex = count - 1; this.records = new SQLRecord[count]; this.lock = new ReentrantLock(); } public SQLRecord[] getRecords() { return records; } /** * 检查当前的值能否进入排名 */ public boolean check(long value) { return (index < count) || (value > minValue); } public void add(SQLRecord record) { final ReentrantLock lock = this.lock; lock.lock(); try { if (index < count) { records[index++] = record; if (index == count) { Arrays.sort(records); minValue = records[0].executeTime; } } else { swap(record); } } finally { lock.unlock(); } } public void clear() { final ReentrantLock lock = this.lock; lock.lock(); try { for (int i = 0; i < count; i++) { records[i] = null; } index = 0; minValue = 0; } finally { lock.unlock(); } } /** * 交换元素位置并重新定义最小值 */ private void swap(SQLRecord record) { int x = find(record.executeTime, 0, lastIndex); switch (x) { case 0: break; case 1: minValue = record.executeTime; records[0] = record; break; default: --x;// 向左移动一格 final SQLRecord[] records = this.records; for (int i = 0; i < x; i++) { records[i] = records[i + 1]; } records[x] = record; minValue = records[0].executeTime; } } /** * 定位v在当前范围内的排名 */ private int find(long v, int from, int to) { int x = from + ((to - from + 1) >> 1); if (v <= records[x].executeTime) { --x;// 向左移动一格 if (from >= x) { return v <= records[from].executeTime ? from : from + 1; } else { return find(v, from, x); } } else { ++x;// 向右移动一格 if (x >= to) { return v <= records[to].executeTime ? to : to + 1; } else { return find(v, x, to); } } } }