xref: /aoo42x/main/store/workben/t_store.cxx (revision cdf0e10c)
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