1 martin 1.25 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.26 //
|
3 martin 1.25 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.26 //
|
10 martin 1.25 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.26 //
|
17 martin 1.25 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.26 //
|
20 martin 1.25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.26 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.26 //
|
28 martin 1.25 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.9 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #ifndef Pegasus_InstanceIndexFile_h
33 #define Pegasus_InstanceIndexFile_h
34
|
35 kumpf 1.17 #include <fstream>
|
36 mike 1.9 #include <Pegasus/Common/Config.h>
37 #include <Pegasus/Common/String.h>
|
38 kumpf 1.16 #include <Pegasus/Common/InternalException.h>
|
39 kumpf 1.13 #include <Pegasus/Common/CIMObjectPath.h>
|
40 kumpf 1.15 #include <Pegasus/Repository/Linkage.h>
|
41 mike 1.9
42 PEGASUS_NAMESPACE_BEGIN
43
|
44 mike 1.11 /** This class manages access to an "instance index file" which maps
|
45 kumpf 1.22 instance names to offsets of the instances contained in the "instance
46 data file".
|
47 mike 1.11
|
48 kumpf 1.24 All files belonging to the instance repository are stored under the
49 repository/instances directory. For each class, two files are maintained:
50 an index file (with a ".idx" extension) and an instance file which bears
51 the name of the class whose instances it contains. For example, suppose
52 there is a class called "Zebra". Then two files are used to manage its
53 instances:
54
55 <pre>
56 repository/instances/Zebra.idx (called the index file)
57 repository/instances/Zebra (called the instance file)
58 </pre>
59
60 The first line of the index file is a free count, expressed as eight hex
|
61 kumpf 1.22 digits followed by a newline. The free count indicates how many instances
62 are free (but not reclaimed). When instances are deleted or modified, the
|
63 mike 1.11 corresponding entry in this index file is marked as free (by changing the
|
64 kumpf 1.24 first column of the entry from '0' to '1'). To improve performance,
65 reclamation of unused space in the instance file (called gaps) is
66 postponed until there are m gaps.
67
68 Reorganization is expensive: the entire instance file and index file must
69 be rewritten. The time complexity is O(n) where n is the number of
70 instances in the file. By postponing reorganization, the time complexity
71 may be reduced to O(1).
|
72 mike 1.11
73 All subsequent lines contain an entry with the following form:
|
74 kumpf 1.22
|
75 mike 1.9 <pre>
|
76 kumpf 1.24 <free> <hash-code> <offset> <size> ClassName.key1=val1,...,keyN=valN
|
77 mike 1.9 </pre>
78
|
79 kumpf 1.24 <ul>
80 <li>
81 free - '1' if the corresponding instance was deleted, '0' otherwise.
82 When instances are deleted, the corresponding entry in the index file
83 is marked as free and a gap is left in the instance file until
84 reorganization time.
85 </li>
86 <li>
87 hash-code - hash code for the key field below. This field is provided to
88 speed lookup of index entries. When looking up an entry, compute the
89 hash code of the key and look for entries with the same hash code.
90 It is still necessary to compare the keys when the hash codes are
91 the same (since collisions are possible), but only when they are the
92 same which is rare and hence this scheme saves many comparisons.
93 </li>
94 <li>
95 offset - offset within the instance file to where the instance begins.
96 </li>
97 <li>
98 size - size in bytes of the instance itself (as it appears in the instance
99 file).
100 kumpf 1.24 </li>
101 <li>
102 key - the compound key of the instance (including all key binding pairs).
103 </li>
104 </ul>
|
105 mike 1.10
|
106 mike 1.11 Here's an example of an index file:
|
107 mike 1.9
108 <pre>
|
109 kumpf 1.22 00000001
110 0 A6B275A9 0 1425 Employee.ssn=444332222
111 1 A6BA08B1 1425 1430 Employee.ssn=555667777
|
112 mike 1.9 </pre>
113
|
114 kumpf 1.24 Notice that the dirty count is equal to one and that one entry is marked
115 as deleted (these quantities must be equal). This indicates that the
116 instance file has one instance which is no longer used. The space used by
117 this instance will be reclaimed during reorganization.
118
119 The layout of the instance file is trivial. Instances are always appended
120 to the instance file. The instances are kept end-to-end in the file.
121
|
122 mike 1.11 To lookup an entry in the index file, first take the hash code of the
123 target key. Then find the first non-free entry whose hash code and key
124 are the same as the target hash code and key. Note that an entry may
125 usually be ruled out by comparing the hash codes (except in the case of
126 clashes).
|
127 kumpf 1.22
|
128 kumpf 1.24 There are three operations which may be performed on the instance
129 repository: create, modify, and delete.
130
131 Creation. During creation, the instance is appended to the instance file
132 and an entry is appended to the index file. If an instance with the same
133 key is found, then the operation is disallowed.
134
135 Deletion. To delete an instance, the corresponding entry in the index file
136 is marked as deleted (by changing the first column from '0' to '1'). And
137 then the dirty count is incremented and updated. If the dirty count has
138 reached the configured threshold, the index and instance files are
139 reogranized.
140
141 Modification. To modify an instance, the new modified instance is appended
142 to the instance file. Next the old entry with the same key is marked as
143 deleted. Finally, a new entry is inserted into the index file.
|
144 mike 1.9 */
145 class PEGASUS_REPOSITORY_LINKAGE InstanceIndexFile
146 {
147 public:
|
148 kumpf 1.22
149 /** Searches the instance index file for the given instance name. Sets
|
150 mike 1.10 the index parameter to the corresponding index, and sets the size
151 parameter to the corresponding instance record size. Returns true
152 on success.
153
|
154 mike 1.11 @param path the file path of the instance index file
155 @param instanceName the name of the instance
156 @param indexOut the index of the instance record found
157 @param sizeOut the size of the instance record found
158 @return true if the instance is found; false otherwise.
|
159 mike 1.9 */
|
160 mike 1.11 static Boolean lookupEntry(
|
161 kumpf 1.22 const String& path,
162 const CIMObjectPath& instanceName,
163 Uint32& indexOut,
164 Uint32& sizeOut);
|
165 mike 1.9
|
166 mike 1.11 /** Creates a new entry in the instance index file. Saves the index and
|
167 mike 1.10 size of the instance record passed in. This method assumes that the
|
168 kumpf 1.22 keys in the instance name are in sorted order. This must be done
|
169 mike 1.10 prior to calling the method. Returns true on success.
170
|
171 mike 1.11 @param path the file path of the instance index file
172 @param instanceName the name of the instance
173 @param indexIn the index of the new instance record
|
174 kumpf 1.22 @param sizeIn the size of the new instance record
|
175 mike 1.11 @return true if successful; false otherwise.
|
176 mike 1.9 */
|
177 mike 1.11 static Boolean createEntry(
|
178 kumpf 1.22 const String& path,
179 const CIMObjectPath& instanceName,
180 Uint32 indexIn,
|
181 mike 1.11 Uint32 sizeIn);
|
182 mike 1.10
|
183 mike 1.11 /** Deletes the entry with the given instance name.
184 @param path path of the instance index file
185 @param instanceName name of the instance
186 @return true on success
|
187 mike 1.9 */
|
188 mike 1.11 static Boolean deleteEntry(
|
189 kumpf 1.22 const String& path,
190 const CIMObjectPath& instanceName,
191 Uint32& freeCount);
|
192 mike 1.9
|
193 mike 1.10 /** Modifies an entry by first removing the old entry and then inserting
|
194 mike 1.11 a new entry at the end of the file.
|
195 mike 1.10
|
196 mike 1.11 @param path the file path of the instance index file.
197 @param instanceName the name of the instance.
198 @param indexIn the index of the modified instance record.
199 @param sizeIn the size of the modified instance record.
200 @return true on success.
|
201 mike 1.10 */
|
202 mike 1.11 static Boolean modifyEntry(
|
203 kumpf 1.22 const String& path,
204 const CIMObjectPath& instanceName,
205 Uint32 indexIn,
|
206 mike 1.10 Uint32 sizeIn,
|
207 kumpf 1.22 Uint32& freeCount);
|
208 mike 1.10
209 /** Gets the information stored in the index file for all the instances
|
210 kumpf 1.22 of the given class. Appends the instance names, indices and sizes
|
211 mike 1.10 to the given arrays (does not clear the arrays first). Returns
212 true on success.
213
|
214 mike 1.11 @param path path of the instance index file.
215 @param instanceNames array to hold the instance names.
216 @param indices array to hold the indices of the instance records.
217 @param sizes an array to hold the sizes of the instance records.
218 @return true on success.
|
219 mike 1.9 */
|
220 mike 1.11 static Boolean enumerateEntries(
|
221 kumpf 1.22 const String& path,
222 Array<Uint32>& freeFlags,
223 Array<Uint32>& indices,
|
224 mike 1.11 Array<Uint32>& sizes,
|
225 kumpf 1.22 Array<CIMObjectPath>& instanceNames,
226 Boolean includeFreeEntries);
|
227 mike 1.11
|
228 kumpf 1.12
|
229 mike 1.11 /** Returns true if this index file has any non-free entries:
230 */
231 static Boolean hasNonFreeEntries(const String& path);
232
233 /** Begin a transaction to modify this file. The effect of subsequent
|
234 kumpf 1.22 modifications can be rolled back by calling rollbackTransaction().
235 The current implementation simply copies the index file to a a file
236 with the same name but with ".rollback" appended to it.
|
237 mike 1.11 */
238 static Boolean beginTransaction(const String& path);
239
|
240 kumpf 1.22 /** Roll back any changes to the file since the last time
|
241 mike 1.11 beginTransaction() was called. The current implementation deletes
|
242 kumpf 1.22 the current file and renames the rollback file to the same name.
|
243 mike 1.11 */
244 static Boolean rollbackTransaction(const String& path);
245
246 /** Commit changes made after beginTransaction() was called. The curent
|
247 kumpf 1.22 implementation simply removes the .rollback file.
|
248 mike 1.11 */
249 static Boolean commitTransaction(const String& path);
250
251 /** Compact the file by removing entries which are marked as free.
252 */
253 static Boolean compact(
254 const String& path);
|
255 mike 1.10
256 private:
|
257 mike 1.11
258 /** Open the index file and position the file pointer on the first
|
259 kumpf 1.22 entry (immediately after the free count). Create the file if it
260 does not exist and if the create flag is true (writing a free
|
261 kumpf 1.12 count of zero).
|
262 mike 1.11 */
263 static Boolean _openFile(
|
264 kumpf 1.22 const String& path,
|
265 kumpf 1.12 PEGASUS_STD(fstream)& fs,
266 Boolean create = false);
|
267 kumpf 1.22
|
268 mike 1.11 /** Appends a new entry to the index file; called by both createEntry()
269 and modifyEntry().
|
270 mike 1.10 */
|
271 mike 1.11 static Boolean _appendEntry(
272 PEGASUS_STD(fstream)& fs,
|
273 kumpf 1.13 const CIMObjectPath& instanceName,
|
274 mike 1.11 Uint32 indexIn,
275 Uint32 sizeIn);
|
276 kumpf 1.22
|
277 mike 1.11 /** Increment the index file's free count; called by _markEntryFree().
|
278 kumpf 1.22 The resulting value is left in the freeCount parameter.
|
279 mike 1.11 */
280 static Boolean _incrementFreeCount(
|
281 kumpf 1.22 PEGASUS_STD(fstream)& fs,
282 Uint32& freeCount);
|
283 mike 1.10
|
284 mike 1.11 /** Marks the entry matching the given instanceName as free; called by both
|
285 kumpf 1.22 deleteEntry() and modifyEntry().
|
286 mike 1.11 */
287 static Boolean _markEntryFree(
288 PEGASUS_STD(fstream)& fs,
|
289 kumpf 1.13 const CIMObjectPath& instanceName);
|
290 mike 1.11
291 /** Helper method for lookupEntry() which takes a file stream rather than
|
292 kumpf 1.22 a path.
|
293 mike 1.11 */
294 static Boolean _lookupEntry(
|
295 kumpf 1.22 PEGASUS_STD(fstream)& fs,
296 const CIMObjectPath& instanceName,
297 Uint32& indexOut,
298 Uint32& sizeOut,
299 Uint32& entryOffset);
|
300 mike 1.9 };
301
302 PEGASUS_NAMESPACE_END
303
304 #endif /* Pegasus_InstanceIndexFile_h */
|