AT&T 2.0.19 Code drop, stage 3
[aaf/authz.git] / auth / auth-core / src / main / java / org / onap / aaf / auth / local / TextIndex.java
diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/local/TextIndex.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/local/TextIndex.java
new file mode 100644 (file)
index 0000000..5169cf8
--- /dev/null
@@ -0,0 +1,256 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.local;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.onap.aaf.auth.local.DataFile.Token;
+import org.onap.aaf.auth.local.DataFile.Token.Field;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+
+public class TextIndex {
+       private static final int REC_SIZE=8;
+       
+       private File file;
+       private DataFile dataFile=null;
+       
+       public TextIndex(File theFile) {
+               file = theFile;
+       }
+       
+       public void open() throws IOException {
+               dataFile = new DataFile(file,"r");
+               dataFile.open();
+       }
+       
+       public void close() throws IOException {
+               if(dataFile!=null) {
+                       dataFile.close();
+                       dataFile=null;
+               }
+       }
+
+       public int find(Object key, AbsData.Reuse reuse, int offset) throws IOException {
+               return find(key,reuse.tokenData,reuse.getFieldData(),offset);
+       }
+       
+       public int find(Object key, DataFile.Token dtok, Field df, int offset) throws IOException {
+               if(dataFile==null) {
+                       throw new IOException("File not opened");
+               }
+               long hash = hashToLong(key.hashCode());
+               int min=0, max = (int)(dataFile.size()/REC_SIZE);
+               Token ttok = dataFile.new Token(REC_SIZE);
+               IntBuffer tib = ttok.getIntBuffer();
+               long lhash;
+               int curr;
+               while((max-min)>100) {
+                       ttok.pos((curr=(min+(max-min)/2))*REC_SIZE);
+                       tib.rewind();
+                       lhash = hashToLong(tib.get());
+                       if(lhash<hash) {
+                               min=curr+1;
+                       } else if(lhash>hash) {
+                               max=curr-1;
+                       } else {
+                               min=curr-40;
+                               max=curr+40;
+                               break;
+                       }
+               }
+               
+               List<Integer> entries = new ArrayList<Integer>();
+               for(int i=min;i<=max;++i) {
+                       ttok.pos(i*REC_SIZE);
+                       tib.rewind();
+                       lhash = hashToLong(tib.get());
+                       if(lhash==hash) {
+                               entries.add(tib.get());
+                       } else if(lhash>hash) {
+                               break;
+                       }
+               }
+               
+               for(Integer i : entries) {
+                       dtok.pos(i);
+                       if(df.at(offset).equals(key)) {
+                               return i;
+                       }
+               }
+               return -1;
+       }
+       
+
+       /*
+        * Have to change Bytes into a Long, to avoid the inevitable signs in the Hash
+        */
+       private static long hashToLong(int hash) {
+               long rv;
+               if(hash<0) {
+                       rv = 0xFFFFFFFFL & hash;
+               } else {
+                       rv = hash;
+               }
+               return rv;
+       }
+       
+       public void create(final Trans trans,final DataFile data, int maxLine, char delim, int fieldOffset, int skipLines) throws IOException {
+               RandomAccessFile raf;
+               FileChannel fos;
+               
+               List<Idx> list = new LinkedList<Idx>(); // Some hashcodes will double... DO NOT make a set
+               TimeTaken tt2 = trans.start("Open Files", Env.SUB);
+               try {
+                       raf = new RandomAccessFile(file,"rw");
+                       raf.setLength(0L);
+                       fos = raf.getChannel();
+               } finally {
+                       tt2.done();
+               }
+               
+               try {
+                       
+                       Token t = data.new Token(maxLine);  
+                       Field f = t.new Field(delim);
+                       
+                       int count = 0;
+                       if(skipLines>0) {
+                               trans.info().log("Skipping",skipLines,"line"+(skipLines==1?" in":"s in"),data.file().getName());
+                       }
+                       for(int i=0;i<skipLines;++i) {
+                               t.nextLine();
+                       }
+                       tt2 = trans.start("Read", Env.SUB);
+                       try {
+                               while(t.nextLine()) {
+                                       list.add(new Idx(f.at(fieldOffset),t.pos()));
+                                       ++count;
+                               }
+                       } finally {
+                               tt2.done();
+                       }
+                       trans.checkpoint("    Read " + count + " records");
+                       tt2 = trans.start("Sort List", Env.SUB);
+                       Collections.sort(list);
+                       tt2.done();
+                       tt2 = trans.start("Write Idx", Env.SUB);
+                       try {
+                               ByteBuffer bb = ByteBuffer.allocate(8*1024);
+                               IntBuffer ib = bb.asIntBuffer();
+                               for(Idx idx : list) {
+                                       if(!ib.hasRemaining()) {
+                                               fos.write(bb);
+                                               ib.clear();
+                                               bb.rewind();
+                                       }
+                                       ib.put(idx.hash);
+                                       ib.put(idx.pos);
+                               }
+                               bb.limit(4*ib.position());
+                               fos.write(bb);
+                       } finally {
+                               tt2.done();
+                       }
+               } finally {
+                       fos.close();
+                       raf.close();
+               }
+       }
+       
+       public class Iter {
+               private int idx;
+               private Token t;
+               private long end;
+               private IntBuffer ib;
+
+
+               public Iter() {
+                       try {
+                               idx = 0;
+                               end = dataFile.size();
+                               t  = dataFile.new Token(REC_SIZE);
+                               ib = t.getIntBuffer();
+
+                       } catch (IOException e) {
+                               end = -1L;
+                       }
+               }
+               
+               public int next() {
+                       t.pos(idx);
+                       ib.clear();
+                       ib.get();
+                       int rec = ib.get();
+                       idx += REC_SIZE;
+                       return rec;
+               }
+
+               public boolean hasNext() {
+                       return idx<end;
+               }
+       }
+       
+       private static class Idx implements Comparable<Idx> {
+               public int hash, pos;
+               public Idx(Object obj, int pos) {
+                       hash = obj.hashCode();
+                       this.pos = pos;
+               }
+               
+               @Override
+               public int compareTo(Idx ib) {
+                       long a = hashToLong(hash);
+                       long b = hashToLong(ib.hash);
+                       return a>b?1:a<b?-1:0;
+               }
+
+               /* (non-Javadoc)
+                * @see java.lang.Object#equals(java.lang.Object)
+                */
+               @Override
+               public boolean equals(Object o) {
+                       if(o!=null && o instanceof Idx) {
+                               return hash == ((Idx)o).hash;
+                       }
+                       return false;
+               }
+
+               /* (non-Javadoc)
+                * @see java.lang.Object#hashCode()
+                */
+               @Override
+               public int hashCode() {
+                       return hash;
+               }
+       }
+}