1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_store.hxx"
26
27 #define _T_STORE_CXX "$Revision$"
28 #include <sal/types.h>
29 #include <osl/diagnose.h>
30 #include <osl/thread.h>
31 #include <osl/time.h>
32 #include <rtl/ustring.hxx>
33 #include <store/store.hxx>
34
35 #include <stdio.h>
36
37 #if (defined(WNT) && defined(PROFILE))
38 extern "C"
39 {
40 void StartCAP (void);
41 void StopCAP (void);
42 void DumpCAP (void);
43 }
44 #endif /* PROFILE */
45
46 using rtl::OUString;
47
48 /*========================================================================
49 *
50 * Internals.
51 *
52 *======================================================================*/
53 #define _DEMOSTOR_BUFSIZ 512 /* 4096, 1024, 512 */
54 #define _DEMOSTOR_LOOPS 1000 /* 1000, 2000 */
55
56 #define _DEMOSTOR_REMOVE 0
57 #define _DEMOSTOR_REBUILD 0
58
59 enum Options
60 {
61 OPTION_HELP = 0x0001,
62 OPTION_FILE = 0x0002,
63 OPTION_PAUSE = 0x0004,
64 OPTION_REBUILD = 0x0008,
65
66 OPTION_DUMP = 0x0010,
67 OPTION_ITER = 0x0020,
68 OPTION_LINK = 0x0040,
69
70 OPTION_READ = 0x0100,
71 OPTION_WRITE = 0x0200,
72 OPTION_CREAT = 0x0400,
73 OPTION_TRUNC = 0x0800
74 };
75
ascii_toLowerCase(sal_Char ch)76 inline sal_Char ascii_toLowerCase (sal_Char ch)
77 {
78 if ((ch >= 0x41) && (ch <= 0x5A))
79 return (ch + 0x20);
80 else
81 return (ch);
82 }
83
84 /*========================================================================
85 *
86 * Timing.
87 *
88 *======================================================================*/
89 struct OTime : public TimeValue
90 {
OTimeOTime91 OTime (void)
92 {
93 Seconds = 0;
94 Nanosec = 0;
95 }
96
getSystemTimeOTime97 static OTime getSystemTime (void)
98 {
99 OTime tv;
100 osl_getSystemTime (&tv);
101 return tv;
102 }
103
operator -=OTime104 OTime& operator-= (const OTime& rPast)
105 {
106 Seconds -= rPast.Seconds;
107 if (Nanosec < rPast.Nanosec)
108 {
109 Seconds -= 1;
110 Nanosec += 1000000000;
111 }
112 Nanosec -= rPast.Nanosec;
113 return *this;
114 }
115
operator -(const OTime & rTimeA,const OTime & rTimeB)116 friend OTime operator- (const OTime& rTimeA, const OTime& rTimeB)
117 {
118 OTime aTimeC (rTimeA);
119 aTimeC -= rTimeB;
120 return aTimeC;
121 }
122 };
123
124 /*========================================================================
125 *
126 * DirectoryTraveller.
127 *
128 *======================================================================*/
129 typedef store::OStoreDirectory Directory;
130
131 class DirectoryTraveller : public Directory::traveller
132 {
133 typedef store::OStoreFile file;
134 typedef Directory::iterator iter;
135
136 store::OStoreFile m_aFile;
137 OUString m_aPath;
138
139 sal_uInt32 m_nOptions;
140 unsigned int m_nLevel;
141 unsigned int m_nCount;
142
143 public:
144 DirectoryTraveller (
145 const file& rFile,
146 const OUString &rPath,
147 const OUString &rName,
148 sal_uInt32 nOptions,
149 unsigned int nLevel = 0);
150
151 virtual ~DirectoryTraveller (void);
152
153 virtual sal_Bool visit (const iter& it);
154 };
155
156 /*
157 * DirectoryTraveller.
158 */
DirectoryTraveller(const file & rFile,const OUString & rPath,const OUString & rName,sal_uInt32 nOptions,unsigned int nLevel)159 DirectoryTraveller::DirectoryTraveller (
160 const file& rFile,
161 const OUString &rPath,
162 const OUString &rName,
163 sal_uInt32 nOptions,
164 unsigned int nLevel)
165 : m_aFile (rFile),
166 m_aPath (rPath),
167 m_nOptions (nOptions),
168 m_nLevel (nLevel),
169 m_nCount (0)
170 {
171 m_aPath += rName;
172 m_aPath += OUString::createFromAscii("/");
173 }
174
175 /*
176 * ~DirectoryTraveller.
177 */
~DirectoryTraveller(void)178 DirectoryTraveller::~DirectoryTraveller (void)
179 {
180 }
181
182 /*
183 * visit.
184 */
visit(const iter & it)185 sal_Bool DirectoryTraveller::visit (const iter& it)
186 {
187 m_nCount++;
188 if (m_nOptions & OPTION_DUMP)
189 {
190 rtl::OString aName (it.m_pszName, it.m_nLength, RTL_TEXTENCODING_UTF8);
191 printf ("Visit(%d,%d): %s [0x%08x] %d [Bytes]\n",
192 m_nLevel, m_nCount,
193 aName.pData->buffer, (unsigned int)(it.m_nAttrib), (unsigned int)(it.m_nSize));
194 }
195 if (it.m_nAttrib & STORE_ATTRIB_ISDIR)
196 {
197 OUString aName (it.m_pszName, it.m_nLength);
198 if (aName.compareToAscii ("XTextViewCursorSupplier") == 0)
199 {
200 m_nCount += 1 - 1;
201 }
202 Directory aSubDir;
203
204 storeError eErrCode = aSubDir.create (
205 m_aFile, m_aPath, aName, store_AccessReadOnly);
206 if (eErrCode == store_E_None)
207 {
208 sal_uInt32 nRefCount = 0;
209 m_aFile.getRefererCount (nRefCount);
210
211 DirectoryTraveller aSubTraveller (
212 m_aFile, m_aPath, aName, m_nOptions, m_nLevel + 1);
213 aSubDir.travel (aSubTraveller);
214 }
215 }
216 return sal_True;
217 }
218
219 /*========================================================================
220 *
221 * main.
222 *
223 *======================================================================*/
main(int argc,char ** argv)224 int SAL_CALL main (int argc, char **argv)
225 {
226 #if (defined(WNT) && defined(PROFILE))
227 StartCAP();
228 #else
229 OTime aMainStartTime (OTime::getSystemTime());
230 #endif /* PROFILE */
231
232 store::OStoreFile aFile;
233 storeError eErrCode = store_E_None;
234
235 sal_uInt32 nOptions = 0;
236 for (int i = 1; i < argc; i++)
237 {
238 const char *opt = argv[i];
239 if (opt[0] == '-')
240 {
241 switch (ascii_toLowerCase(sal_Char(opt[1])))
242 {
243 case 'f':
244 nOptions |= OPTION_FILE;
245 break;
246
247 case 'd':
248 nOptions |= OPTION_DUMP;
249 break;
250 case 'i':
251 nOptions |= OPTION_ITER;
252 break;
253 case 'l':
254 nOptions |= OPTION_LINK;
255 break;
256
257 case 'r':
258 nOptions |= OPTION_READ;
259 break;
260 case 'w':
261 nOptions |= OPTION_WRITE;
262 break;
263 case 'c':
264 nOptions |= OPTION_CREAT;
265 break;
266 case 't':
267 nOptions |= OPTION_TRUNC;
268 break;
269
270 case 'p':
271 nOptions |= OPTION_PAUSE;
272 break;
273
274 case 'h':
275 default:
276 nOptions |= OPTION_HELP;
277 break;
278 }
279 }
280 else
281 {
282 if (nOptions & OPTION_FILE)
283 {
284 OUString aName (
285 argv[i], rtl_str_getLength(argv[i]),
286 osl_getThreadTextEncoding());
287 if ((nOptions & OPTION_CREAT) && (nOptions & OPTION_TRUNC))
288 eErrCode = aFile.create (aName, store_AccessCreate);
289 else if (nOptions & OPTION_CREAT)
290 eErrCode = aFile.create (aName, store_AccessReadCreate);
291 else if (nOptions & OPTION_WRITE)
292 eErrCode = aFile.create (aName, store_AccessReadWrite);
293 else
294 eErrCode = aFile.create (aName, store_AccessReadOnly);
295 if (eErrCode != store_E_None)
296 {
297 printf ("Error: can't open file: %s\n", argv[i]);
298 exit (0);
299 }
300 }
301 }
302 }
303
304 if ((nOptions == 0) || (nOptions & OPTION_HELP))
305 {
306 printf ("Usage:\tt_store "
307 "[[-c] [-t] [-r] [-w]] [[-i] [-d] [-h]] "
308 "[-f filename]\n");
309
310 printf ("\nOptions:\n");
311 printf ("-c\tcreate\n");
312 printf ("-t\ttruncate\n");
313 printf ("-r\tread\n");
314 printf ("-w\twrite\n");
315 printf ("-i\titerate\n");
316 printf ("-d\tdump\n");
317 printf ("-h\thelp\n");
318 printf ("-f\tfilename\n");
319
320 printf ("\nExamples:");
321 printf ("\nt_store -c -w -f t_store.rdb\n");
322 printf ("\tCreate file 't_store.rdb',\n"
323 "\twrite fixed number (1000) of streams.\n");
324 printf ("\nt_store -c -i -d -f t_store.rdb\n");
325 printf ("\tOpen file 't_store.rdb', "
326 "create '/' directory,\n"
327 "\titerate directory tree, "
328 "dump directory info.\n");
329
330 exit (0);
331 }
332
333 if (!aFile.isValid())
334 {
335 eErrCode = aFile.createInMemory();
336 if (eErrCode != store_E_None)
337 {
338 printf ("Error: can't create memory file\n");
339 exit (0);
340 }
341 }
342
343 // Stream Read/Write.
344 OUString aPath (RTL_CONSTASCII_USTRINGPARAM("/"));
345 if ((nOptions & OPTION_READ) || (nOptions & OPTION_WRITE))
346 {
347 // Mode.
348 storeAccessMode eMode = store_AccessReadOnly;
349 if (nOptions & OPTION_WRITE)
350 eMode = store_AccessReadWrite;
351 if (nOptions & OPTION_CREAT)
352 eMode = store_AccessCreate;
353
354 // Buffer.
355 char pBuffer[_DEMOSTOR_BUFSIZ] = "Hello World";
356 pBuffer[_DEMOSTOR_BUFSIZ - 2] = 'B';
357 pBuffer[_DEMOSTOR_BUFSIZ - 1] = '\0';
358
359 // Load/Save.
360 #ifndef PROFILE
361 OTime aStartTime (OTime::getSystemTime());
362 #endif /* PROFILE */
363
364 for (int i = 0; i < _DEMOSTOR_LOOPS; i++)
365 {
366 OUString aName (RTL_CONSTASCII_USTRINGPARAM("demostor-"));
367 aName += OUString::valueOf ((sal_Int32)(i + 1), 10);
368 aName += OUString::createFromAscii (".dat");
369
370 #if (_DEMOSTOR_REMOVE == 1)
371 eErrCode = aFile.remove (aPath, aName);
372 if ((eErrCode != store_E_None ) &&
373 (eErrCode != store_E_NotExists) )
374 break;
375 #endif /* _REMOVE */
376
377 store::OStoreStream aStream;
378 eErrCode = aStream.create (aFile, aPath, aName, eMode);
379 if (eErrCode != store_E_None)
380 {
381 OSL_TRACE("OStoreStream(%d)::create(): error: %d", i, eErrCode);
382 break;
383 }
384
385 if (nOptions & OPTION_TRUNC)
386 {
387 eErrCode = aStream.setSize(0);
388 if (eErrCode != store_E_None)
389 {
390 OSL_TRACE("OStoreStream(%d)::setSize(0): error: %d", i, eErrCode);
391 break;
392 }
393 }
394
395 sal_uInt32 nDone = 0;
396 if (nOptions & OPTION_WRITE)
397 {
398 eErrCode = aStream.writeAt (
399 0, pBuffer, sizeof(pBuffer), nDone);
400 if (eErrCode != store_E_None)
401 {
402 OSL_TRACE("OStoreStream(%d)::writeAt(): error: %d", i, eErrCode);
403 break;
404 }
405 }
406
407 if (nOptions & OPTION_READ)
408 {
409 sal_uInt32 nOffset = 0;
410 for (;;)
411 {
412 eErrCode = aStream.readAt (
413 nOffset, pBuffer, sizeof(pBuffer), nDone);
414 if (eErrCode != store_E_None)
415 {
416 OSL_TRACE("OStoreStream(%d)::readAt(): error: %d", i, eErrCode);
417 break;
418 }
419 if (nDone == 0)
420 break;
421 nOffset += nDone;
422 }
423 }
424
425 aStream.close();
426
427 #ifndef PROFILE
428 if (((i + 1) % (_DEMOSTOR_LOOPS/10)) == 0)
429 {
430 OTime aDelta (OTime::getSystemTime() - aStartTime);
431
432 sal_uInt32 nDelta = aDelta.Seconds * 1000000;
433 nDelta += (aDelta.Nanosec / 1000);
434
435 printf ("%d: %12.4g[usec]\n", (i+1),
436 (double)(nDelta)/(double)(i+1));
437 }
438 #endif /* PROFILE */
439 }
440
441 #ifndef PROFILE
442 OTime aDelta (OTime::getSystemTime() - aStartTime);
443
444 sal_uInt32 nDelta = aDelta.Seconds * 1000000;
445 nDelta += (aDelta.Nanosec / 1000);
446
447 printf ("Total(rd,wr): %d[usec]\n", (unsigned int)(nDelta));
448 #endif /* PROFILE */
449 }
450
451 // Link/Rename.
452 if (nOptions & OPTION_LINK)
453 {
454 // Create symlink to (root) directory.
455 eErrCode = aFile.symlink (
456 aPath, OUString::createFromAscii("000000/"),
457 OUString(), aPath);
458 OSL_POSTCOND(
459 ((eErrCode == store_E_None ) ||
460 (eErrCode == store_E_AlreadyExists) ),
461 "t_store::main(): store_symlink() failed");
462
463 // Create symlink to file.
464 OUString aLinkName (RTL_CONSTASCII_USTRINGPARAM("demostor-1.lnk"));
465
466 eErrCode = aFile.symlink (
467 aPath, aLinkName,
468 aPath, OUString::createFromAscii("demostor-1.dat"));
469 OSL_POSTCOND(
470 ((eErrCode == store_E_None ) ||
471 (eErrCode == store_E_AlreadyExists) ),
472 "t_store::main(): store_symlink() failed");
473 if ((eErrCode == store_E_None ) ||
474 (eErrCode == store_E_AlreadyExists) )
475 {
476 OUString aShortcut (
477 RTL_CONSTASCII_USTRINGPARAM("Shortcut to demostor-1.dat"));
478 eErrCode = aFile.rename (
479 aPath, aLinkName,
480 aPath, aShortcut);
481 OSL_POSTCOND(
482 ((eErrCode == store_E_None ) ||
483 (eErrCode == store_E_AlreadyExists) ),
484 "t_store::main(): store_rename() failed");
485 }
486
487 // Create directory.
488 OUString aDirName (RTL_CONSTASCII_USTRINGPARAM("demostor-1.dir"));
489 store::OStoreDirectory aDir;
490
491 eErrCode = aDir.create (
492 aFile, aPath, aDirName, store_AccessReadCreate);
493 OSL_POSTCOND(
494 (eErrCode == store_E_None),
495 "t_store::main(): store_createDirectory() failed");
496 if (eErrCode == store_E_None)
497 {
498 #if 0 /* NYI */
499 // Rename directory.
500 eErrCode = aFile.rename (
501 aPath, "demostor-1.dir/",
502 aPath, "Renamed demostor-1.dir");
503 OSL_POSTCOND(
504 ((eErrCode == store_E_None ) ||
505 (eErrCode == store_E_AlreadyExists) ),
506 "t_store::main(): store_rename() failed");
507
508 eErrCode = aFile.rename (
509 aPath, "Renamed demostor-1.dir/",
510 aPath, "demostor-1.dir");
511 OSL_POSTCOND(
512 (eErrCode == store_E_None),
513 "t_store::main(): store_rename() failed");
514 #endif /* NYI */
515 }
516 }
517
518 // Directory iteration.
519 if (nOptions & OPTION_ITER)
520 {
521 #ifndef PROFILE
522 OTime aStartTime (OTime::getSystemTime());
523 #endif /* PROFILE */
524 OUString aEmpty;
525
526 // Root directory.
527 store::OStoreDirectory aRootDir;
528 if (nOptions & OPTION_LINK)
529 {
530 // Open symlink entry.
531 eErrCode = aRootDir.create (
532 aFile, aPath, OUString::createFromAscii("000000"),
533 store_AccessReadOnly);
534 }
535 else
536 {
537 // Open direct entry.
538 if (nOptions & OPTION_CREAT)
539 eErrCode = aRootDir.create (
540 aFile, aEmpty, aEmpty, store_AccessReadCreate);
541 else if (nOptions & OPTION_WRITE)
542 eErrCode = aRootDir.create (
543 aFile, aEmpty, aEmpty, store_AccessReadWrite);
544 else
545 eErrCode = aRootDir.create (
546 aFile, aEmpty, aEmpty, store_AccessReadOnly);
547 }
548
549 if (eErrCode == store_E_None)
550 {
551 // Traverse directory tree.
552 DirectoryTraveller aTraveller (
553 aFile, aEmpty, aEmpty, nOptions, 0);
554 aRootDir.travel (aTraveller);
555 }
556 else
557 {
558 // Failure.
559 printf ("Error: can't open directory: \"/\"\n");
560 }
561
562 #ifndef PROFILE
563 OTime aDelta (OTime::getSystemTime() - aStartTime);
564
565 sal_uInt32 nDelta = aDelta.Seconds * 1000000;
566 nDelta += (aDelta.Nanosec / 1000);
567
568 printf ("Total(iter): %d[usec]\n", (unsigned int)(nDelta));
569 #endif /* PROFILE */
570 }
571
572 if (nOptions & OPTION_PAUSE)
573 {
574 TimeValue tv;
575 tv.Seconds = 300;
576 tv.Nanosec = 0;
577 osl_waitThread (&tv);
578 }
579
580 // Size.
581 sal_uInt32 nSize = 0;
582 aFile.getSize (nSize);
583
584 // Done.
585 aFile.close();
586
587 #if (defined(WNT) && defined(PROFILE))
588 StopCAP();
589 DumpCAP();
590 #endif /* PROFILE */
591 #ifndef PROFILE
592 OTime aDelta (OTime::getSystemTime() - aMainStartTime);
593
594 sal_uInt32 nDelta = aDelta.Seconds * 1000000;
595 nDelta += (aDelta.Nanosec / 1000);
596
597 printf ("Total: %d[usec]\n", (unsigned int)(nDelta));
598 #endif /* PROFILE */
599
600 return 0;
601 }
602