69d6d6982d077276a4551d9b304bf7c636f1a997
[aaf/authz.git] / authz-core / src / main / java / com / att / authz / local / AbsData.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aaf\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
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \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
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package com.att.authz.local;\r
24 \r
25 import java.io.File;\r
26 import java.io.FileNotFoundException;\r
27 import java.io.IOException;\r
28 import java.io.RandomAccessFile;\r
29 import java.util.Iterator;\r
30 \r
31 import com.att.authz.env.AuthzTrans;\r
32 import com.att.authz.local.DataFile.Token;\r
33 import com.att.authz.local.DataFile.Token.Field;\r
34 import com.att.inno.env.Env;\r
35 import com.att.inno.env.TimeTaken;\r
36 \r
37 public abstract class AbsData implements Iterable<String> {\r
38         protected DataFile data;\r
39         protected TextIndex ti;\r
40         private File dataf,idxf,lockf;\r
41         private String name;\r
42         private char delim;\r
43         private int maxLineSize;\r
44         private int fieldOffset;\r
45         private int skipLines;\r
46 \r
47         public AbsData(File dataf,char sepChar, int maxLineSize, int fieldOffset) {\r
48                 File dir = dataf.getParentFile();\r
49                 int dot = dataf.getName().lastIndexOf('.');\r
50                 if(dot>=0) {\r
51                         name = dataf.getName().substring(0,dot);\r
52                 }\r
53 \r
54                 this.dataf=dataf;\r
55                 this.delim = sepChar;\r
56                 this.maxLineSize = maxLineSize;\r
57                 this.fieldOffset = fieldOffset;\r
58                 idxf = new File(dir,name.concat(".idx"));\r
59                 lockf = new File(dir,name.concat(".lock"));\r
60                 \r
61                 \r
62                 data = new DataFile(dataf,"r");\r
63                 ti = new TextIndex(idxf);\r
64                 skipLines=0;\r
65         }\r
66         \r
67         public void skipLines(int lines) {\r
68                 skipLines=lines;\r
69         }\r
70         \r
71         public String name() {\r
72                 return name;\r
73         }\r
74         \r
75         public void open(AuthzTrans trans, long timeout) throws IOException {\r
76                 TimeTaken tt = trans.start("Open Data File", Env.SUB);\r
77                 boolean opened = false, first = true;\r
78                 try {\r
79                                 if(!dataf.exists()) {\r
80                                         throw new FileNotFoundException("Data File Missing:" + dataf.getCanonicalPath());\r
81                                 }\r
82                                 long begin = System.currentTimeMillis();\r
83                                 long end = begin+timeout;\r
84                                 boolean exists;\r
85                                 while((exists=lockf.exists()) && begin<end) {\r
86                                         if(first) {\r
87                                                 trans.warn().log("Waiting for",lockf.getCanonicalPath(),"to close");\r
88                                                 first = false;\r
89                                         } \r
90                                         try {\r
91                                                 Thread.sleep(200);\r
92                                         } catch (InterruptedException e) {\r
93                                                 break;\r
94                                         }\r
95                                         begin = System.currentTimeMillis();\r
96                                 }\r
97                                 if(exists) {\r
98                                         throw new IOException(lockf.getCanonicalPath() + "exists.  May not open Datafile");\r
99                                 }\r
100                                 data.open();\r
101                                 try {\r
102                                         ensureIdxGood(trans);\r
103                                 } catch (IOException e) {\r
104                                         data.close();\r
105                                         throw e;\r
106                                 }\r
107                                 ti.open();\r
108                                 opened = true;\r
109                         \r
110                 } finally {\r
111                         tt.done();\r
112                 }\r
113                 if(!opened) {\r
114                         throw new IOException("DataFile pair for " + name + " was not able to be opened in " + timeout + "ms");\r
115                 }\r
116         }\r
117         \r
118         private synchronized void ensureIdxGood(AuthzTrans trans) throws IOException {\r
119                 if(!idxf.exists() || idxf.length()==0 || dataf.lastModified()>idxf.lastModified()) {\r
120                         trans.warn().log(idxf.getCanonicalPath(),"is missing, empty or out of date, creating");\r
121                         RandomAccessFile raf = new RandomAccessFile(lockf, "rw");\r
122                         try {\r
123                                 ti.create(trans, data, maxLineSize, delim, fieldOffset, skipLines);\r
124                                 if(!idxf.exists() || (idxf.length()==0 && dataf.length()!=0)) {\r
125                                         throw new IOException("Data Index File did not create correctly");\r
126                                 }\r
127                         } finally {\r
128                                 raf.close();\r
129                                 lockf.delete();\r
130                         }\r
131                 }\r
132         }\r
133 \r
134         public void close(AuthzTrans trans) throws IOException {\r
135                 ti.close();\r
136                 data.close();\r
137         }\r
138         \r
139         public class Reuse {\r
140                 private Token tokenData;\r
141                 private Field fieldData;\r
142 \r
143                 private Reuse(int size,char delim) {\r
144                         tokenData = data.new Token(size);\r
145                         fieldData = getTokenData().new Field(delim);\r
146                 }\r
147                 \r
148                 public void reset() {\r
149                         getFieldData().reset();\r
150                 }\r
151 \r
152                 public void pos(int rec) {\r
153                         getFieldData().reset();\r
154                         getTokenData().pos(rec);\r
155                 }\r
156 \r
157                 public String next() {\r
158                         return getFieldData().next();\r
159                 }\r
160                 \r
161                 public String at(int field) {\r
162                         return getFieldData().at(field);\r
163                 }\r
164 \r
165                 public String atToEnd(int field) {\r
166                         return getFieldData().atToEnd(field);\r
167                 }\r
168 \r
169                 public Field getFieldData() {\r
170                         return fieldData;\r
171                 }\r
172 \r
173                 public Token getTokenData() {\r
174                         return tokenData;\r
175                 }\r
176 \r
177         }\r
178         \r
179         public Reuse reuse() {\r
180                 return new Reuse(maxLineSize,delim);\r
181         }\r
182 \r
183         public Iter iterator() {\r
184                 return new Iter();\r
185         }\r
186         \r
187         public class Iter implements Iterator<String> {\r
188                 private Reuse reuse;\r
189                 private com.att.authz.local.TextIndex.Iter tii;\r
190 \r
191                 public Iter() {\r
192                         reuse = reuse();\r
193                         tii = ti.new Iter();\r
194                 }\r
195 \r
196                 @Override\r
197                 public boolean hasNext() {\r
198                         return tii.hasNext();\r
199                 }\r
200 \r
201                 @Override\r
202                 public String next() {\r
203                         reuse.reset();\r
204                         int rec = tii.next();\r
205                         reuse.pos(rec);\r
206                         return reuse.at(0);\r
207                 }\r
208 \r
209                 @Override\r
210                 public void remove() {\r
211                         // read only\r
212                 }\r
213         }\r
214 }\r