1 kumpf 1.1.2.1 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 kumpf 1.1.2.1 //==============================================================================
23 //
24 // Author: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
25 //
26 // Modified By:
27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30 #include <fstream>
31 #include <Pegasus/Common/Destroyer.h>
32 #include <Pegasus/Common/FileSystem.h>
33 #include <Pegasus/Common/XmlWriter.h>
34 #include "InstanceFile.h"
35
36 // Note: If the INDENT_XML_FILES option is set, the XmlWriter is called
37 // to parse the xml data to add indentations before saving the
38 // instance data to the instance file. It somewhat impacts the
39 // performance of a create or modify instance operation. In the
40 // future, this option should be made a configurable property to
41 // allow enabling and disabling without re-compilation.
42
43 kumpf 1.1.2.1 #define INDENT_XML_FILES
44
45 PEGASUS_USING_STD;
46
47 PEGASUS_NAMESPACE_BEGIN
48
49 /**
50 Loads an instance record in the instance file to memory.
51 */
52 Boolean InstanceFile::loadInstance(
53 const String& path,
54 Uint32 index,
55 Uint32 size,
56 Array<Sint8>& data)
57 {
58 //
59 // check for the existence of the instance file, and get the real path
60 // of the file
61 //
62 String realPath;
63
64 kumpf 1.1.2.1 if (!FileSystem::existsNoCase(path, realPath))
65 {
66 return false;
67 }
68
69 //
70 // load data from file
71 //
72 if (!_loadData(realPath, index, size, data))
73 {
74 return false;
75 }
76
77 return true;
78 }
79
80 /**
81 Loads all the instance records in the instance file to memory.
82 */
83 Boolean InstanceFile::loadAllInstances(
84 const String& path,
85 kumpf 1.1.2.1 Array<Sint8>& data)
86 {
87 //
88 // check for the existence of the instance file, and get the real path
89 // of the file
90 //
91 String realPath;
92
93 if (!FileSystem::existsNoCase(path, realPath))
94 {
95 return false;
96 }
97
98 //
99 // get the size of the instance file
100 //
101 Uint32 fileSize;
102 if (!FileSystem::getFileSizeNoCase(realPath, fileSize))
103 {
104 return false;
105 }
106 kumpf 1.1.2.1
107 //
108 // load all the instance data stored in the instance file
109 //
110 if (!_loadData(realPath, 0, fileSize, data))
111 {
112 return false;
113 }
114
115 return true;
116 }
117
118 /**
119 Inserts a new record into the instance file. Sets the byte position
120 and the size of the newly added instance record. Returns true on
121 success.
122
123 This method creates a temporary file, copies the contents of the original
124 instance file to the temporary file, and appends the new entry to the
125 temporary file. The caller must rename the temporary file back to the
126 original file after the insert operation is successful on BOTH the
127 kumpf 1.1.2.1 instance index file and the instance file.
128 */
129 Boolean InstanceFile::insertInstance(
130 Array<Sint8> out,
131 const String& path,
132 Uint32& index,
133 Uint32& size)
134 {
135 //
136 // Create a temporary instance file
137 //
138 // First make sure that there is not already a temporary file.
139 // If a temporary file already exists, remove it first.
140 //
141 String tempFilePath;
142 if (FileSystem::existsNoCase(path + ".tmp", tempFilePath))
143 {
144 if (!FileSystem::removeFileNoCase(tempFilePath))
145 {
146 return false;
147 }
148 kumpf 1.1.2.1 }
149
150 ArrayDestroyer<char> p(path.allocateCString(4));
151 strcat(p.getPointer(), ".tmp");
152 ofstream os(p.getPointer(), ios::app | ios::binary);
153
154 if (!os)
155 {
156 return false;
157 }
158
159 //
160 // Check for the existence of the instance file. If file exists, copy
161 // the contents of the file to the temporary file.
162 //
163 String realPath;
164 if (FileSystem::existsNoCase(path, realPath))
165 {
166 ArrayDestroyer<char> p(realPath.allocateCString());
167 ifstream is(p.getPointer());
168
169 kumpf 1.1.2.1 if (!is)
170 {
171 return false;
172 }
173
174 //
175 // get the size of the instance file
176 //
177 Uint32 fileSize;
178 if (!FileSystem::getFileSizeNoCase(realPath, fileSize))
179 {
180 return false;
181 }
182
183 char* buffer = new char[fileSize];
184 is.clear();
185 is.seekg(0);
186 is.read(buffer, fileSize);
187
188 if (is.fail())
189 return false;
190 kumpf 1.1.2.1
191 os.write(buffer, fileSize);
192
193 delete [] buffer;
194
195 is.close();
196 }
197
198 //
199 // append the new instance to the end of the file
200 //
201 if (!_insertData(out, os, index, size))
202 {
203 return false;
204 }
205
206 os.close();
207
208 return true;
209 }
210
211 kumpf 1.1.2.1 /**
212 Removes an instance record from the instance file.
213
214 This method creates a temporary file, then calls removeData() to remove
215 the entry from the temporary file. The caller must rename the temporary
216 file back to the original file after the remove operation is successful
217 on BOTH the instance index file and the instance file.
218 */
219 Boolean InstanceFile::removeInstance(
220 const String& path,
221 Uint32 size,
222 Uint32 index)
223 {
224 //
225 // check for the existence of the instance file, and get the real path
226 // of the file
227 //
228 String realPath;
229
230 if (!FileSystem::existsNoCase(path, realPath))
231 {
232 kumpf 1.1.2.1 return false;
233 }
234
235 //
236 // Create a temporary instance index file
237 //
238 // First make sure that there is not already a temporary file.
239 // If a temporary file already exists, remove it first.
240 //
241 String tempFilePath;
242 if (FileSystem::existsNoCase(realPath + ".tmp", tempFilePath))
243 {
244 if (!FileSystem::removeFileNoCase(tempFilePath))
245 {
246 return false;
247 }
248 }
249
250 ArrayDestroyer<char> p(realPath.allocateCString(4));
251 strcat(p.getPointer(), ".tmp");
252 ofstream os(p.getPointer(), ios::app | ios::binary);
253 kumpf 1.1.2.1
254 if (!os)
255 {
256 return false;
257 }
258
259 //
260 // remove the entry from file
261 //
262 if (!_removeData(realPath, os, size, index))
263 {
264 return false;
265 }
266
267 os.close();
268
269 return true;
270 }
271
272 /**
273 Modifies an instance record in the instance file by first removing the
274 kumpf 1.1.2.1 the old instance record in the instance file, then appends the new
275 instance record to the instance file. Returns the byte position and the
276 size of the newly added instance record.
277
278 This method creates a temporary file. All updates are done to the
279 temporary file. The caller must rename the temporary file back to the
280 the original file after the modify operation is successful on BOTH the
281 instance index file and the instance file.
282 */
283 Boolean InstanceFile::modifyInstance(
284 Array<Sint8> out,
285 const String& path,
286 Uint32 oldIndex,
287 Uint32 oldSize,
288 Uint32& newIndex,
289 Uint32& newSize)
290 {
291 //
292 // check for the existence of the instance file, and get the real path
293 // of the file
294 //
295 kumpf 1.1.2.1 String realPath;
296
297 if (!FileSystem::existsNoCase(path, realPath))
298 {
299 return false;
300 }
301
302 //
303 // Open a temporary instance file
304 //
305 // First make sure that there is not already a temporary file.
306 // If a temporary file already exists, remove it first.
307 //
308 String tempFilePath;
309 if (FileSystem::existsNoCase(realPath + ".tmp", tempFilePath))
310 {
311 if (!FileSystem::removeFileNoCase(tempFilePath))
312 {
313 return false;
314 }
315 }
316 kumpf 1.1.2.1
317 ArrayDestroyer<char> p(realPath.allocateCString(4));
318 strcat(p.getPointer(), ".tmp");
319 ofstream os(p.getPointer(), ios::app | ios::binary);
320
321 if (!os)
322 {
323 return false;
324 }
325
326 //
327 // remove the old entry from the temporary file
328 //
329 if (!_removeData(realPath, os, oldSize, oldIndex))
330 {
331 return false;
332 }
333
334 //
335 // Append the new instance to the instance file
336 //
337 kumpf 1.1.2.1 if (!_insertData(out, os, newIndex, newSize))
338 {
339 return false;
340 }
341
342 os.close();
343
344 return true;
345 }
346
347 /**
348 Loads data from the instance file at the given byte positon for the
349 given size.
350 */
351 Boolean InstanceFile::_loadData(
352 const String& path,
353 Uint32 index,
354 Uint32 size,
355 Array<Sint8>& data)
356 {
357 //
358 kumpf 1.1.2.1 // open the instance file
359 //
360 ArrayDestroyer<char> p(path.allocateCString());
361 ifstream is(p.getPointer(), ios::in);
362
363 if (!is)
364 {
365 return false;
366 }
367
368 //
369 // position the file get pointer at the specified location
370 //
371 is.clear();
372 is.seekg(index);
373
374 //
375 // Load data from file into memory
376 //
377 char* buffer = new char[size];
378 is.read( buffer, size);
379 kumpf 1.1.2.1
380 if (is.fail())
381 return false;
382
383 data.clear();
384 data.reserve(size+1);
385 data.append(buffer, size);
386 data.append('\0');
387
388 is.close();
389
390 delete [] buffer;
391
392 return true;
393 }
394
395 /**
396 Removes a record in the instance file at the given byte position for
397 the given size.
398 */
399 Boolean InstanceFile::_removeData(
400 kumpf 1.1.2.1 const String& realPath,
401 ofstream& os,
402 Uint32 size,
403 Uint32 index)
404 {
405 //
406 // Open the instance file
407 //
408 ArrayDestroyer<char> q(realPath.allocateCString());
409 ifstream is(q.getPointer(), ios::in);
410
411 if (!is)
412 {
413 return false;
414 }
415
416 //
417 // get the size of the instance file
418 //
419 Uint32 fileSize;
420 if (!FileSystem::getFileSizeNoCase(realPath, fileSize))
421 kumpf 1.1.2.1 {
422 return false;
423 }
424
425 //
426 // Copy all the entries in the instance file up to the one to be deleted
427 //
428 Array<Sint8> data;
429 Uint32 copySize;
430 Uint32 sizeNeeded;
431
432 //
433 // determine the number of bytes to copy
434 //
435 sizeNeeded = fileSize - size;
436
437 //
438 // if the entry to be deleted is not the only entry in the instance file,
439 // copy the remaining entries
440 //
441 if (sizeNeeded > 0)
442 kumpf 1.1.2.1 {
443 char* buffer = new char[sizeNeeded];
444
445 data.clear();
446 data.reserve(sizeNeeded);
447
448 is.clear();
449
450 //
451 // copy from the beginning of the file if the entry to be deleted
452 // is not the first entry in the file
453 //
454 if (index != 0)
455 {
456 is.seekg(0);
457 is.read( buffer, index );
458
459 if (is.fail())
460 return false;
461
462 data.append(buffer, index);
463 kumpf 1.1.2.1 }
464
465 //
466 // skip the entry to be deleted and copy the remaining entries
467 //
468 Uint32 placeToCopy = index + size;
469
470 is.seekg(placeToCopy);
471 copySize = (fileSize - placeToCopy) - 1;
472
473 is.read( buffer, copySize );
474
475 if (is.fail())
476 return false;
477
478 data.append(buffer, copySize);
479 data.append('\0');
480
481 delete [] buffer;
482
483 //
484 kumpf 1.1.2.1 // write data to the temporary file
485 //
486 os << (char*)data.getData() << endl;
487
488 os.flush();
489 }
490
491 is.close();
492
493 return true;
494 }
495
496 /**
497 Inserts a new record into the instance file.
498
499 */
500 Boolean InstanceFile::_insertData(
501 Array<Sint8> out,
502 ofstream& os,
503 Uint32& index,
504 Uint32& size)
505 kumpf 1.1.2.1 {
506 Uint32 begPos; // file position before insertion
507 Uint32 endPos; // file position after insertion
508
509 //
510 // determine current position of file
511 //
512 begPos = os.tellp();
513 index = begPos;
514
515 //
516 // write the CIM/XML encoding of the instance to file
517 //
518 #ifdef INDENT_XML_FILES
519 out.append('\0');
520 XmlWriter::indentedPrint(os, out.getData(), 2);
521 #else
522 os.write((char*)out.getData(), out.size());
523 #endif
524
525 //
526 kumpf 1.1.2.1 // determine the size of the instance record written to file
527 //
528 endPos = os.tellp();
529 size = endPos - begPos;
530
531 os.flush();
532
533 return true;
534 }
535
536 PEGASUS_NAMESPACE_END
|