--- /dev/null
+/*******************************************************************************\r
+ * ============LICENSE_START====================================================\r
+ * * org.onap.aaf\r
+ * * ===========================================================================\r
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
+ * * ===========================================================================\r
+ * * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * * you may not use this file except in compliance with the License.\r
+ * * You may obtain a copy of the License at\r
+ * * \r
+ * * http://www.apache.org/licenses/LICENSE-2.0\r
+ * * \r
+ * * Unless required by applicable law or agreed to in writing, software\r
+ * * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * * See the License for the specific language governing permissions and\r
+ * * limitations under the License.\r
+ * * ============LICENSE_END====================================================\r
+ * *\r
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
+ * *\r
+ ******************************************************************************/\r
+package org.onap.aaf.authz.local;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+import java.util.Iterator;\r
+\r
+import org.onap.aaf.authz.env.AuthzTrans;\r
+import org.onap.aaf.authz.local.DataFile.Token;\r
+import org.onap.aaf.authz.local.DataFile.Token.Field;\r
+\r
+import org.onap.aaf.inno.env.Env;\r
+import org.onap.aaf.inno.env.TimeTaken;\r
+\r
+public abstract class AbsData implements Iterable<String> {\r
+ protected DataFile data;\r
+ protected TextIndex ti;\r
+ private File dataf,idxf,lockf;\r
+ private String name;\r
+ private char delim;\r
+ private int maxLineSize;\r
+ private int fieldOffset;\r
+ private int skipLines;\r
+\r
+ public AbsData(File dataf,char sepChar, int maxLineSize, int fieldOffset) {\r
+ File dir = dataf.getParentFile();\r
+ int dot = dataf.getName().lastIndexOf('.');\r
+ if(dot>=0) {\r
+ name = dataf.getName().substring(0,dot);\r
+ }\r
+\r
+ this.dataf=dataf;\r
+ this.delim = sepChar;\r
+ this.maxLineSize = maxLineSize;\r
+ this.fieldOffset = fieldOffset;\r
+ idxf = new File(dir,name.concat(".idx"));\r
+ lockf = new File(dir,name.concat(".lock"));\r
+ \r
+ \r
+ data = new DataFile(dataf,"r");\r
+ ti = new TextIndex(idxf);\r
+ skipLines=0;\r
+ }\r
+ \r
+ public void skipLines(int lines) {\r
+ skipLines=lines;\r
+ }\r
+ \r
+ public String name() {\r
+ return name;\r
+ }\r
+ \r
+ public void open(AuthzTrans trans, long timeout) throws IOException {\r
+ TimeTaken tt = trans.start("Open Data File", Env.SUB);\r
+ boolean opened = false, first = true;\r
+ try {\r
+ if(!dataf.exists()) {\r
+ throw new FileNotFoundException("Data File Missing:" + dataf.getCanonicalPath());\r
+ }\r
+ long begin = System.currentTimeMillis();\r
+ long end = begin+timeout;\r
+ boolean exists;\r
+ while((exists=lockf.exists()) && begin<end) {\r
+ if(first) {\r
+ trans.warn().log("Waiting for",lockf.getCanonicalPath(),"to close");\r
+ first = false;\r
+ } \r
+ try {\r
+ Thread.sleep(200);\r
+ } catch (InterruptedException e) {\r
+ break;\r
+ }\r
+ begin = System.currentTimeMillis();\r
+ }\r
+ if(exists) {\r
+ throw new IOException(lockf.getCanonicalPath() + "exists. May not open Datafile");\r
+ }\r
+ data.open();\r
+ try {\r
+ ensureIdxGood(trans);\r
+ } catch (IOException e) {\r
+ data.close();\r
+ throw e;\r
+ }\r
+ ti.open();\r
+ opened = true;\r
+ \r
+ } finally {\r
+ tt.done();\r
+ }\r
+ if(!opened) {\r
+ throw new IOException("DataFile pair for " + name + " was not able to be opened in " + timeout + "ms");\r
+ }\r
+ }\r
+ \r
+ private synchronized void ensureIdxGood(AuthzTrans trans) throws IOException {\r
+ if(!idxf.exists() || idxf.length()==0 || dataf.lastModified()>idxf.lastModified()) {\r
+ trans.warn().log(idxf.getCanonicalPath(),"is missing, empty or out of date, creating");\r
+ RandomAccessFile raf = new RandomAccessFile(lockf, "rw");\r
+ try {\r
+ ti.create(trans, data, maxLineSize, delim, fieldOffset, skipLines);\r
+ if(!idxf.exists() || (idxf.length()==0 && dataf.length()!=0)) {\r
+ throw new IOException("Data Index File did not create correctly");\r
+ }\r
+ } finally {\r
+ raf.close();\r
+ lockf.delete();\r
+ }\r
+ }\r
+ }\r
+\r
+ public void close(AuthzTrans trans) throws IOException {\r
+ ti.close();\r
+ data.close();\r
+ }\r
+ \r
+ public class Reuse {\r
+ private Token tokenData;\r
+ private Field fieldData;\r
+\r
+ private Reuse(int size,char delim) {\r
+ tokenData = data.new Token(size);\r
+ fieldData = getTokenData().new Field(delim);\r
+ }\r
+ \r
+ public void reset() {\r
+ getFieldData().reset();\r
+ }\r
+\r
+ public void pos(int rec) {\r
+ getFieldData().reset();\r
+ getTokenData().pos(rec);\r
+ }\r
+\r
+ public String next() {\r
+ return getFieldData().next();\r
+ }\r
+ \r
+ public String at(int field) {\r
+ return getFieldData().at(field);\r
+ }\r
+\r
+ public String atToEnd(int field) {\r
+ return getFieldData().atToEnd(field);\r
+ }\r
+\r
+ public Field getFieldData() {\r
+ return fieldData;\r
+ }\r
+\r
+ public Token getTokenData() {\r
+ return tokenData;\r
+ }\r
+\r
+ }\r
+ \r
+ public Reuse reuse() {\r
+ return new Reuse(maxLineSize,delim);\r
+ }\r
+\r
+ public Iter iterator() {\r
+ return new Iter();\r
+ }\r
+ \r
+ public class Iter implements Iterator<String> {\r
+ private Reuse reuse;\r
+ private org.onap.aaf.authz.local.TextIndex.Iter tii;\r
+\r
+ public Iter() {\r
+ reuse = reuse();\r
+ tii = ti.new Iter();\r
+ }\r
+\r
+ @Override\r
+ public boolean hasNext() {\r
+ return tii.hasNext();\r
+ }\r
+\r
+ @Override\r
+ public String next() {\r
+ reuse.reset();\r
+ int rec = tii.next();\r
+ reuse.pos(rec);\r
+ return reuse.at(0);\r
+ }\r
+\r
+ @Override\r
+ public void remove() {\r
+ // read only\r
+ }\r
+ }\r
+}\r