1 karl 1.21 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.4 //
|
3 karl 1.15 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.14 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.15 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.16 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.21 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.4 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
15 kumpf 1.6 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
18 mike 1.4 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.25 //
|
21 kumpf 1.6 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
22 mike 1.4 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
24 kumpf 1.6 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
27 mike 1.4 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
|
34 mike 1.5 #include <Pegasus/Common/Config.h>
|
35 kumpf 1.8 #include <Pegasus/Common/InternalException.h>
|
36 mike 1.4 #include <Pegasus/Common/FileSystem.h>
37 #include <Pegasus/Common/Exception.h>
|
38 mike 1.23 #include <Pegasus/Common/ReadWriteSem.h>
|
39 mike 1.4 #include "AssocClassTable.h"
40
41 PEGASUS_USING_STD;
42
43 PEGASUS_NAMESPACE_BEGIN
44
45 #define ASSOC_CLASS_NAME_INDEX 0
46 #define FROM_CLASS_NAME_INDEX 1
47 #define FROM_PROPERTY_NAME_INDEX 2
48 #define TO_CLASS_NAME_INDEX 3
49 #define TO_PROPERTY_NAME_INDEX 4
50 #define NUM_FIELDS 5
51
|
52 r.kieninger 1.19
53 ReadWriteSem AssocClassTable::_classCacheLock;
54
55
|
56 mike 1.4 static inline Boolean _MatchNoCase(const String& x, const String& pattern)
57 {
58 return pattern.size() == 0 || String::equalNoCase(x, pattern);
59 }
60
|
61 kumpf 1.24 static inline Boolean _ContainsClass(
62 const Array<CIMName>& classNames,
63 const String& match)
|
64 karl 1.11 {
65 Uint32 n = classNames.size();
66
67 for (Uint32 i = 0; i < n; i++)
68 {
|
69 david.dillard 1.18 if (_MatchNoCase(classNames[i].getString(), match))
70 return true;
|
71 karl 1.11 }
72
73 return false;
74 }
75
|
76 mike 1.4 static Boolean _GetRecord(ifstream& is, Array<String>& fields)
77 {
78 fields.clear();
79 String line;
80
81 for (Uint32 i = 0; i < NUM_FIELDS; i++)
82 {
|
83 kumpf 1.24 if (!GetLine(is, line))
84 return false;
|
85 mike 1.4
|
86 r.kieninger 1.19 fields.append(line);
87 //Association names are not supposed to contain escapes
88 //fields.append(_Unescape(line));
|
89 mike 1.4 }
90
91 // Skip the blank line:
92
93 if (!GetLine(is, line))
|
94 kumpf 1.24 return false;
|
95 mike 1.4
96 return true;
97 }
98
99 static void _PutRecord(ofstream& os, Array<String>& fields)
100 {
101 for (Uint32 i = 0, n = fields.size(); i < n; i++)
|
102 chuck 1.17 {
|
103 kumpf 1.26 // Write the field in UTF-8. Call write() to ensure no data
104 // conversion by the stream. Since all the fields contain CIM names,
105 // it is not necessary to escape CR/LF characters.
106 CString buffer = fields[i].getCString();
|
107 kumpf 1.20 os.write((const char *)buffer,
108 static_cast<streamsize>(strlen((const char *)buffer)));
|
109 chuck 1.17 os << endl;
110 }
|
111 mike 1.4 os << endl;
112 }
113
114 void AssocClassTable::append(
115 PEGASUS_STD(ofstream)& os,
|
116 r.kieninger 1.19 const String& path,
|
117 kumpf 1.10 const CIMName& assocClassName,
118 const CIMName& fromClassName,
119 const CIMName& fromPropertyName,
120 const CIMName& toClassName,
121 const CIMName& toPropertyName)
|
122 mike 1.4 {
123 Array<String> fields;
|
124 kumpf 1.7 fields.reserveCapacity(5);
|
125 kumpf 1.10 fields.append(assocClassName.getString());
126 fields.append(fromClassName.getString());
127 fields.append(fromPropertyName.getString());
128 fields.append(toClassName.getString());
129 fields.append(toPropertyName.getString());
|
130 mike 1.4
|
131 r.kieninger 1.19
|
132 mike 1.4 _PutRecord(os, fields);
|
133 r.kieninger 1.19
134 // Update cache
|
135 kumpf 1.24 AssocClassCache* cache = AssocClassCache::getAssocClassCache(path);
|
136 r.kieninger 1.19 if (cache != 0)
137 {
138 if (cache->isActive())
139 {
140 WriteLock lock(_classCacheLock);
141 cache->addRecord(fields[FROM_CLASS_NAME_INDEX],
142 fields);
143 }
144 }
|
145 mike 1.4 }
146
147 void AssocClassTable::append(
148 const String& path,
|
149 kumpf 1.10 const CIMName& assocClassName,
150 const CIMName& fromClassName,
151 const CIMName& fromPropertyName,
152 const CIMName& toClassName,
153 const CIMName& toPropertyName)
|
154 mike 1.4 {
155 // Open input file:
|
156 david.dillard 1.18
|
157 mike 1.4 ofstream os;
158
159 if (!OpenAppend(os, path))
|
160 kumpf 1.24 throw CannotOpenFile(path);
|
161 mike 1.4
162 // Insert the entry:
163
164 Array<String> fields;
|
165 kumpf 1.7 fields.reserveCapacity(5);
|
166 kumpf 1.10 fields.append(assocClassName.getString());
167 fields.append(fromClassName.getString());
168 fields.append(fromPropertyName.getString());
169 fields.append(toClassName.getString());
170 fields.append(toPropertyName.getString());
|
171 mike 1.4
|
172 r.kieninger 1.19
|
173 mike 1.4 _PutRecord(os, fields);
|
174 r.kieninger 1.19
175 // Update cache
|
176 kumpf 1.24 AssocClassCache* cache = AssocClassCache::getAssocClassCache(path);
|
177 r.kieninger 1.19 if (cache != 0)
178 {
179 if (cache->isActive())
180 {
181 WriteLock lock(_classCacheLock);
182 cache->addRecord(fields[FROM_CLASS_NAME_INDEX],
183 fields);
184 }
185 }
|
186 mike 1.4 }
187
188 Boolean AssocClassTable::deleteAssociation(
189 const String& path,
|
190 kumpf 1.10 const CIMName& assocClassName)
|
191 mike 1.4 {
192 // Open input file:
193
194 ifstream is;
195
196 if (!Open(is, path))
|
197 kumpf 1.24 return false;
|
198 mike 1.4
199 // Open output file:
200
201 String tmpPath = path + ".tmp";
202 ofstream os;
203
204 if (!Open(os, tmpPath))
|
205 kumpf 1.24 throw CannotOpenFile(tmpPath);
|
206 mike 1.4
207 // Copy over all lines except ones with the given association instance name:
208
209 Array<String> fields;
|
210 r.kieninger 1.19 Array<String> fieldsToDelete;
|
211 mike 1.4 Boolean found = false;
212
213 while (_GetRecord(is, fields))
214 {
|
215 kumpf 1.24 if (assocClassName.getString() != fields[ASSOC_CLASS_NAME_INDEX])
216 {
217 _PutRecord(os, fields);
218 found = true;
219 }
|
220 r.kieninger 1.19 else
221 {
222 fieldsToDelete = fields;
223 }
|
224 mike 1.4 }
225
226 // Close both files:
227
228 is.close();
229 os.close();
230
231 // Remove orginal file:
232
233 if (!FileSystem::removeFile(path))
|
234 kumpf 1.24 throw CannotRemoveFile(path);
|
235 mike 1.4
236 // Rename back to original name:
237
238 if (!FileSystem::renameFile(tmpPath, path))
|
239 kumpf 1.24 throw CannotRenameFile(path);
|
240 mike 1.4
|
241 r.kieninger 1.19
242 // Update cache
243 if (found)
244 {
|
245 kumpf 1.24 AssocClassCache* cache = AssocClassCache::getAssocClassCache(path);
|
246 r.kieninger 1.19 if (cache != 0)
247 {
248 if (cache->isActive())
249 {
250 WriteLock lock(_classCacheLock);
251 cache->removeRecord(fieldsToDelete[FROM_CLASS_NAME_INDEX],
252 fieldsToDelete[ASSOC_CLASS_NAME_INDEX]);
253 }
254 }
255 }
256
|
257 mike 1.4 return found;
258 }
259
260 Boolean AssocClassTable::getAssociatorNames(
261 const String& path,
|
262 kumpf 1.13 const Array<CIMName>& classList,
263 const Array<CIMName>& assocClassList,
264 const Array<CIMName>& resultClassList,
|
265 mike 1.4 const String& role,
266 const String& resultRole,
267 Array<String>& associatorNames)
268 {
269 // Open input file:
270 ifstream is;
271
272 if (!Open(is, path))
|
273 kumpf 1.13 return false;
|
274 mike 1.4
275 Array<String> fields;
276 Boolean found = false;
277
|
278 kumpf 1.13 // For each line in the associations table:
|
279 mike 1.4 while (_GetRecord(is, fields))
280 {
|
281 kumpf 1.13 // Process associations from the right end class and with right roles
282 if (_ContainsClass(classList, fields[FROM_CLASS_NAME_INDEX]) &&
283 _MatchNoCase(fields[FROM_PROPERTY_NAME_INDEX], role) &&
284 _MatchNoCase(fields[TO_PROPERTY_NAME_INDEX], resultRole))
285 {
286 // Skip classes that do not appear in the association class list
287 if ((assocClassList.size() != 0) &&
288 (!_ContainsClass(assocClassList,
289 fields[ASSOC_CLASS_NAME_INDEX])))
290 {
291 continue;
292 }
293
294 // Skip classes that do not appear in the result class list
295 if ((resultClassList.size() != 0) &&
296 (!_ContainsClass(resultClassList,
297 fields[TO_CLASS_NAME_INDEX])))
298 {
299 continue;
300 }
301
302 kumpf 1.13 // This class qualifies; add it to the list (skipping duplicates)
303 if (!Contains(associatorNames, fields[TO_CLASS_NAME_INDEX]))
304 {
305 associatorNames.append(fields[TO_CLASS_NAME_INDEX]);
306 }
307 found = true;
308 }
|
309 mike 1.4 }
310
311 return found;
312 }
313
|
314 kumpf 1.24 Boolean AssocClassTable::_InitializeCache(
315 AssocClassCache* cache,
316 const String& path)
|
317 r.kieninger 1.19 {
318 WriteLock lock(_classCacheLock);
319
320 if (!cache->isActive())
321 {
322
323 // Open input file:
324 ifstream is;
325
326 if (!Open(is, path))
327 return false;
328
329 Array<String> fields;
330
331 // For each line in the associations table:
332 while (_GetRecord(is, fields))
333 {
334 cache->addRecord(fields[FROM_CLASS_NAME_INDEX],
335 fields);
336 }
337
338 r.kieninger 1.19 cache->setActive(true);
339 }
340
341 return true;
342 }
343
344 void AssocClassTable::removeCaches()
345 {
346 WriteLock lock(_classCacheLock);
347 AssocClassCache::cleanupAssocClassCaches();
348
349 return;
350 }
351
|
352 mike 1.4 Boolean AssocClassTable::getReferenceNames(
353 const String& path,
|
354 karl 1.11 const Array<CIMName>& classList,
|
355 kumpf 1.13 const Array<CIMName>& resultClassList,
|
356 mike 1.4 const String& role,
357 Array<String>& referenceNames)
358 {
359
|
360 r.kieninger 1.19 // First see if we can get the information from the association class cache.
|
361 kumpf 1.24 AssocClassCache* cache = AssocClassCache::getAssocClassCache(path);
|
362 r.kieninger 1.19 if (cache == 0)
|
363 kumpf 1.13 return false;
|
364 mike 1.4
|
365 r.kieninger 1.19 if (!cache->isActive())
366 {
367 if (!_InitializeCache(cache,path))
368 return false;
369 }
370
371 Array< Array<String> > records;
|
372 karl 1.11 Boolean found = false;
373
|
374 r.kieninger 1.19
375 // For each of the target classes retrieve the list of matching
376 // association classes from the cache.
377 // The cache uses the from class name as an index and returns all
378 // association class records having that from class.
379
380 ReadLock lock(_classCacheLock);
381 for (Uint16 idx=0; idx < classList.size(); idx++)
|
382 karl 1.11 {
|
383 r.kieninger 1.19 String fromClassName = classList[idx].getString();
384 if (cache->getAssocClassEntry(fromClassName, records))
385 {
386 for (Uint16 rx=0; rx <records.size(); rx++)
387 {
388 if (_MatchNoCase(records[rx][FROM_PROPERTY_NAME_INDEX], role))
|
389 kumpf 1.24 {
390 // Skip classes that do not appear in the result class list
391 if ((resultClassList.size() != 0) &&
392 (!_ContainsClass(resultClassList,
393 records[rx][ASSOC_CLASS_NAME_INDEX])))
394 {
395 continue;
396 }
397
398 // This class qualifies; add it to the list (skipping
399 // duplicates)
400 if (!Contains(referenceNames,
401 records[rx][ASSOC_CLASS_NAME_INDEX]))
402 {
403 referenceNames.append(
404 records[rx][ASSOC_CLASS_NAME_INDEX]);
405 }
406 found = true;
407 }
|
408 kumpf 1.13 }
|
409 r.kieninger 1.19 }
410 }
|
411 mike 1.4
412 return found;
413 }
414
415 PEGASUS_NAMESPACE_END
|