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: 1.7.8.2 $" 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 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 { 91 OTime (void) 92 { 93 Seconds = 0; 94 Nanosec = 0; 95 } 96 97 static OTime getSystemTime (void) 98 { 99 OTime tv; 100 osl_getSystemTime (&tv); 101 return tv; 102 } 103 104 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 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 */ 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 */ 178 DirectoryTraveller::~DirectoryTraveller (void) 179 { 180 } 181 182 /* 183 * visit. 184 */ 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 *======================================================================*/ 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