001 /**
002 *
003 * Copyright 2004 Protique Ltd
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 **/
018
019 package org.activemq.util;
020 import java.util.LinkedList;
021
022 /**
023 * Holder for many bitArrays - used for message audit
024 *
025 * @version $Revision: 1.1.1.1 $
026 */
027 public class BitArrayBin {
028 private LinkedList list;
029 private int maxNumberOfArrays;
030 private int firstIndex = -1;
031 private int firstBin = -1;
032
033 /**
034 * Create a BitArrayBin to a certain window size (number of messages to keep)
035 *
036 * @param windowSize
037 */
038 public BitArrayBin(int windowSize) {
039 maxNumberOfArrays = ((windowSize + 1) / BitArray.LONG_SIZE) + 1;
040 maxNumberOfArrays = Math.max(maxNumberOfArrays, 1);
041 list = new LinkedList();
042 for (int i = 0;i < maxNumberOfArrays;i++) {
043 list.add(new BitArray());
044 }
045 }
046
047 /**
048 * Set a bit
049 *
050 * @param index
051 * @param value
052 * @return
053 */
054 public boolean setBit(long index, boolean value) {
055 boolean answer = true;
056 BitArray ba = getBitArray(index);
057 if (ba != null) {
058 int offset = getOffset(index);
059 if (offset >= 0) {
060 answer = ba.set(offset, value);
061 }
062 }
063 return answer;
064 }
065
066 /**
067 * Get the boolean value at the index
068 *
069 * @param index
070 * @return true/false
071 */
072 public boolean getBit(long index) {
073 boolean answer = index >= firstIndex;
074 BitArray ba = getBitArray(index);
075 if (ba != null) {
076 int offset = getOffset(index);
077 if (offset >= 0) {
078 answer = ba.get(offset);
079 return answer;
080 }
081 }
082 else {
083 //gone passed range for previous bins so assume set
084 answer = true;
085 }
086 return answer;
087 }
088
089 /**
090 * Get the BitArray for the index
091 *
092 * @param index
093 * @return
094 */
095 private BitArray getBitArray(long index) {
096 int bin = getBin(index);
097 BitArray answer = null;
098 if (bin >= 0) {
099 if (firstIndex < 0) {
100 firstIndex = 0;
101 }
102 if (bin >= list.size()) {
103 list.removeFirst();
104 firstIndex += BitArray.LONG_SIZE;
105 list.add(new BitArray());
106 bin = list.size() - 1;
107 }
108 answer = (BitArray) list.get(bin);
109 }
110 return answer;
111 }
112
113 /**
114 * Get the index of the bin from the total index
115 *
116 * @param index
117 * @return the index of the bin
118 */
119 private int getBin(long index) {
120 int answer = 0;
121 if (firstBin < 0) {
122 firstBin = 0;
123 }
124 else if (firstIndex >= 0) {
125 answer = (int) ((index - firstIndex) / BitArray.LONG_SIZE);
126 }
127 return answer;
128 }
129
130 /**
131 * Get the offset into a bin from the total index
132 *
133 * @param index
134 * @return the relative offset into a bin
135 */
136 private int getOffset(long index) {
137 int answer = 0;
138 if (firstIndex >= 0) {
139 //System.out.println("getOffset(" + index + ") firstIndex = " + firstIndex + " bin = " + getBin(index));
140 answer = (int) ((index - firstIndex) - (BitArray.LONG_SIZE * getBin(index)));
141 }
142 return answer;
143 }
144 }