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