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