1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package com.att.authz.local;
\r
25 import java.io.File;
\r
26 import java.io.IOException;
\r
27 import java.io.RandomAccessFile;
\r
28 import java.nio.ByteBuffer;
\r
29 import java.nio.IntBuffer;
\r
30 import java.nio.channels.FileChannel;
\r
31 import java.util.ArrayList;
\r
32 import java.util.Collections;
\r
33 import java.util.LinkedList;
\r
34 import java.util.List;
\r
36 import com.att.authz.local.DataFile.Token;
\r
37 import com.att.authz.local.DataFile.Token.Field;
\r
38 import com.att.inno.env.Env;
\r
39 import com.att.inno.env.TimeTaken;
\r
40 import com.att.inno.env.Trans;
\r
42 public class TextIndex {
\r
43 private static final int REC_SIZE=8;
\r
46 private DataFile dataFile=null;
\r
48 public TextIndex(File theFile) {
\r
52 public void open() throws IOException {
\r
53 dataFile = new DataFile(file,"r");
\r
57 public void close() throws IOException {
\r
58 if(dataFile!=null) {dataFile.close();}
\r
61 public int find(Object key, AbsData.Reuse reuse, int offset) throws IOException {
\r
62 return find(key,reuse.getTokenData(),reuse.getFieldData(),offset);
\r
65 public int find(Object key, DataFile.Token dtok, Field df, int offset) throws IOException {
\r
66 if(dataFile==null) {throw new IOException("File not opened");}
\r
67 long hash = hashToLong(key.hashCode());
\r
68 int min=0, max = (int)(dataFile.size()/REC_SIZE);
\r
69 Token ttok = dataFile.new Token(REC_SIZE);
\r
70 IntBuffer tib = ttok.getIntBuffer();
\r
73 while((max-min)>100) {
\r
74 ttok.pos((curr=(min+(max-min)/2))*REC_SIZE);
\r
76 lhash = hashToLong(tib.get());
\r
79 } else if(lhash>hash) {
\r
88 List<Integer> entries = new ArrayList<Integer>();
\r
89 for(int i=min;i<=max;++i) {
\r
90 ttok.pos(i*REC_SIZE);
\r
92 lhash = hashToLong(tib.get());
\r
94 entries.add(tib.get());
\r
95 } else if(lhash>hash) {
\r
100 for(Integer i : entries) {
\r
102 if(df.at(offset).equals(key)) {
\r
111 * Have to change Bytes into a Long, to avoid the inevitable signs in the Hash
\r
113 private static long hashToLong(int hash) {
\r
116 rv = 0xFFFFFFFFL & hash;
\r
123 public void create(final Trans trans,final DataFile data, int maxLine, char delim, int fieldOffset, int skipLines) throws IOException {
\r
124 RandomAccessFile raf;
\r
127 List<Idx> list = new LinkedList<Idx>(); // Some hashcodes will double... DO NOT make a set
\r
128 TimeTaken tt2 = trans.start("Open Files", Env.SUB);
\r
130 raf = new RandomAccessFile(file,"rw");
\r
132 fos = raf.getChannel();
\r
139 Token t = data.new Token(maxLine);
\r
140 Field f = t.new Field(delim);
\r
144 trans.info().log("Skipping",skipLines,"line"+(skipLines==1?" in":"s in"),data.file().getName());
\r
146 for(int i=0;i<skipLines;++i) {
\r
149 tt2 = trans.start("Read", Env.SUB);
\r
151 while(t.nextLine()) {
\r
152 list.add(new Idx(f.at(fieldOffset),t.pos()));
\r
158 trans.checkpoint(" Read " + count + " records");
\r
159 tt2 = trans.start("Sort List", Env.SUB);
\r
160 Collections.sort(list);
\r
162 tt2 = trans.start("Write Idx", Env.SUB);
\r
164 ByteBuffer bb = ByteBuffer.allocate(8*1024);
\r
165 IntBuffer ib = bb.asIntBuffer();
\r
166 for(Idx idx : list) {
\r
167 if(!ib.hasRemaining()) {
\r
175 bb.limit(4*ib.position());
\r
186 public class Iter {
\r
190 private IntBuffer ib;
\r
196 end = dataFile.size();
\r
197 t = dataFile.new Token(REC_SIZE);
\r
198 ib = t.getIntBuffer();
\r
200 } catch (IOException e) {
\r
205 public int next() {
\r
209 int rec = ib.get();
\r
214 public boolean hasNext() {
\r
219 private static class Idx implements Comparable<Idx> {
\r
220 public int hash, pos;
\r
221 public Idx(Object obj, int pos) {
\r
222 hash = obj.hashCode();
\r
227 public int compareTo(Idx ib) {
\r
228 long a = hashToLong(hash);
\r
229 long b = hashToLong(ib.hash);
\r
230 return a>b?1:a<b?-1:0;
\r
234 * @see java.lang.Object#equals(java.lang.Object)
\r
237 public boolean equals(Object o) {
\r
238 if(o!=null && o instanceof Idx) {
\r
239 return hash == ((Idx)o).hash;
\r
245 * @see java.lang.Object#hashCode()
\r
248 public int hashCode() {
\r