iozone3_488/src/current/Changes.txt0000444000175000017500000036600213573734166016453 0ustar cappscappsV1.0 (capps): Capps: Beginning of the code base. Isom: Added reread Added rewrite Added read backwards Added lseek+read Added lseek+reread Capps: Added more accurate time collection method. Added alignment in the on chip Cache code. Added change step when passing 16 Meg size file. Capps: Added auto+ to purge on chip cache. kcollins: replaced the lseek+read &reread test with random reads and writes Capps: Replaced reverse re-read with record rewrite. This gives both source and destination on chip cache hits. Capps: added auto+multi Support for multiple buffers in the iozone. Capps: Removed the recursion through main(). Cleaned up the printout when not in auto mode. Added support for stride-read. ( Manual mode only ) Capps: Cleanup so it will build for bsd4_2 ( C series machines ) Capps: Cleanup on frontend. Now uses getopt() and has a real parser. Cleanup on error handling. Added throughput tests. Eliminated page faults in the throughput tests. Capps: Made all perf tests table driven. Add back Bill's Copyright. ansify, prototypes, scope limitations. V2.1 (kcollins): Simplified auto mode logic. auto test now runs from MEGABYTES_START to MEGABYTES_END and from RECLEN_START to RECLEN_END with values multiplied by MULTIPLIER each iteration. Range set to (4K...16M) for RECLEN and (1M...512M) for MEGABYTES. (the physical I/O tests for RECLEN <4K take several hours on a 1200). Enlarged MAXBUFFERSIZE to 16MB for large record tests. Added error checking for mallocs (!-). Changed multibuffer code to use all of MAXBUFFERSIZE as a circular buffer, with the number of buffers varying as MAXBUFFERSIZE/reclen. This corrects problems where MAXBUFFERSIZE*MAXBUFFERS was very large. Also modified auto mode so that tests where reclen>filesize are skipped. Modified preadv code to vary the number of buffers as necessary such that they will fit in min(MAXBUFFERSIZE,filesize). This fixes problems where the number of buffers in the i/o vector exceeded the size of mainbuffer. Added bzero for buffer when it is first malloc'd. This ensures that it is initialized before use. Created a script (profile.fs) that runs a series of tests to generate a "box" around common application variables such as filesize, buffer size, buffer encachement, and number of concurrent processes. This is intended to serve as the "standard" filesystem profile. buffer reset to mainbuffer before each test loop V2.3 (kcollins): added -F option to write to specify pathnames for throughput tests (allowing throughput tests to multiple filesystems). V2.4 (capps): Changed preadv/pwritev to use a non-sequential access pattern. Changed the version number. Moved all user interface values to KB. This simplifies the user interface. (consistant scaling) and it also allows one to start with 512kb file. This is very important since the first indirect block causes a significant slowdown in the initial write cases. V2.5 (capps): Re-structure and cleanup. V2.6 (kcollins) Bug fix for the throughput tests. V2.7 (capps): Added -o flag. This makes all file opens for writes have the O_SYNC flag set. This makes all writes go to disk before competion. This is useful for seeing what the media can do without the buffer cache helping. V2.8 (capps): Added -V flag. This turns on pattern verification. If the user were to type: -V 165 Then bit pattern 0xa5 would be placed in every byte in the buffer and when read back from buffer cache, or disk, it will be verified to be correct. If it fails then the error handler will specify the byte location of the miscompare. V2.9 (capps): Added fread/re-fread, fwrite/re-fwrite to list of tests. Added -E to allow the user to run pread and friends as an option. V2.10 (capps): Added -R. This will generate Excel compatible files that can then be imported into Excel and graphed. Added support for 5 targets to the makefile. Added -M This prints out the uname -a stuff about a machine. Added -O This gives all results in operations/sec instead of KB/sec. More code cleanup. Update comments. V2.11 (kcollins) added -A. Auto mode with no crossover and read/write tests only changed default record size to 64KB (from 512 bytes) V2.12 (capps) Added shared memory barrier sync for throughput mode. This provides much finer control over the actual timeing of the children. Added mmap() for BSD (Convex) machines that do not have System V shared memory. Added two ways of showing throughput results. The second method takes into consideration children that lag behind due to slow devices, and gives results that are more accurate. Cleanup of some tab problems in throughput results. Cleanup of floating point output taking to much space. Added -d to allow a variable delay comming out of the barrier in the throughput tests. V2.12 (kcollins) added declaration for create_list to make ansi c compiles work several fixes to some of the SPPUX 5.x make targets added date run to banner (hope this doesn't break your scripts $-) V2.13 (capps) Added "stone walling". During throughput tests, if one process finishes then all others are sent a signal to tell them to stop. (The parallel region has finished). This provides better numbers for throughput. Only bzero or fill min(reclen,CACHE_SIZE) this saves a bunch of paging on workstations with small memory systems. Fixed broken target in the makefile. Note: use of -d is not advised. It makes the children not run in parallel. V2.14 (capps) Bug fix to avoid anomaly in SPP-UX. In SPP-UX the filesystem code preallocates meta-data to improve initial file writes. The first indirect block allocation was causing a block of zeros to be written syncronously. In SPP-UX the filesytem code preallocates zero filled blocks when the first writer touches a filesystem after a sync. A pool of on disk zero'd blocks are created asynchronously and handed out to writers when they cross the boundry into the first level indirect and would have had to stop and wait for the zero filled block to be written. Iozone's testing methodology was not allowing the OS to have any time to complete the async pre-allocation and was not showing the speed up that real applications would see. V2.15 (capps) Improve throughput testing mode. V2.16 (capps) Added -U option. This allows the filesystem to be unmounted and remounted between tests. This guarentees that the buffer cache is cold. V2.17 (capps) Added -T option. This makes the throughput tests use threads instead of processes. Currently using pthread_create(), pthread_self(), and pthread_exit(). Cleaned up file cleanup mechanism. Control C will now cause all temp files to be deleted. Removed all signals used to control sub-processes. V2.18 (capps) Cleanup. Added read stride, read backwards to the throughput tests. Various bug fixes V2.19 (capps) Removed all calls to malloc() and all use of system V shared memory. mmap() is much easier to deal with. As for malloc() HP programs are very limited on the ammount of malloc() space and not nearly so constrained on mmap() memory. It was necessary to move to mmap() since multiple threads all need buffers in the processes address space. Removed dependency on first thread being number 2. Iozone now probes to find out what the thread library will return for the first thread. This makes the switching thread libraries much easier. V2.20 (capps) Children now set stop_flag and shutdown all other children.There is no further need to tell the parent to distribute the stop_flag. verify, purge, and osync are now supported in the throughput tests. Fixed bug where pthreads stack size was causing segmentation violation when purgeit() was called for buffer that were greater than 256kb. V2.21 (capps) Enhanced throughput reporting. Now provides: Child throughput, Parent throughput, Minimum throughput for any child in the group, Maximum throughput for any child in the group, and Minimum transfer count. Due to stone walling not all children write the full requested size. This minimum transfer count provides the user with knowledge of how much work was performed by the slowest child. Added -C flag. This allows the user to see all of the transfer counts for each child. Had to add system 5 shared memory back. Linux does not support mmap(MAP_ANONYMOUS|MAP_SHARED). So it must use SYSV shared memory get get sharing working. V2.22 (capps) Made changes to make iozone work correctly on Linux on a PC. Changes are just scaling down the test to fit on a pc, and scaling down shared segments to < 16 Meg so it can run on an Intel 386 class machine. Added: -L # Set the processor cache line size in bytes. Added: -S # Set the processor cache size in kbytes. Removed spin wait in parent waiting for threads to finish each throughput test. Code not uses thread_join(). Fixed -O (operations/sec) mode to work in throughput tests. V2.23 (capps) Close small timing hole where thread/process has set stop flag and others are in a system call. The hole allowed threads/processes to continue to increment work done after one had finished and told the others to stop. The result was that the children would report slightly high numbers as they were not truely parallel at the finish line. Added random read throughput test. Fixes for VxFS small extents being created by prime_zb() functions. Provides more details about the throughput run. V2.24 (capps) Added support for -R (Excell chart generation) to the throughput tests. Also added support for the -O (ops/sec) to the throughput Excell chart. V2.25 (capps) Added support for selecting which test to run. -i # -i 0 -i 3 will run write and read-backwards tests only. For a list of the test numbers type iozone -h. V2.26 (capps) Added support for LARGE_FILES for the hpux-11.0 target. V2.27 (capps) All tests now verify one long word of data from each page written/read to/from the file. This is to level the playing field with systems that do not move data when "read" or "write" is called, but instead just map the file and perform the I/O when the address space is touched. Benchmarks that do not validate the data ,at least touch each page, do not measure the read/write times just the map times. Note: The -V option still verifies each byte of the buffer, the default is now to verify one long from each page. V2.28 (capps) Added support for benchmarking mmap() files. Added more command line options. -B -G -D B = Use mmap() files for the benchmark. G = Use msync(MS_SYNC) for mmap files. D = Use msync(MS_ASYNC) for mmap files. V2.29 (capps) Bug fixes for: Combination of running individual tests and mmap() files support. Stride read bug that caused only portions of the total file to be examined. V2.30 (capps) Fixups for build under SPP-UX V2.31 (capps) Fixups for build under Linux. Added -j ### to support user setting the stride size for the stride read benchmark. V2.32 (capps) Add support for IRIX and IRIX64. V2.33 (capps) Add support for POSIX async I/O benchmarking. Uses a library to interface to POSIX async I/O model. The library provides and extended async_read() interface. It takes the standard calling options of read() but also allows the application to perform read-ahead with a stride. (positive or negative) and allows the user to specify how much read ahead to perform. Tested on HP-UX 11.0, Linux, SGI Origin. V2.34 (capps) Added -k. This allows POSIX async I/O to utilize the buffer specified and not to perform any bcopys. Fixes to make multi-threadedness work on SGI Origin. V2.34 (capps) Added [-k #]. This allows POSIX async I/O to utilize the buffer specified and not to perform any bcopys. Fixes to make multi-threadedness work on SGI Origin. V2.36 (capps) Iozone is now a 64 bit application. It may be compiled for either 64 bit or 32 bit machines. The makefile supports 64 and 32 bit targets for machines that support 32 & 64 bit targets. All version numbers are now automatically generated by RCS. This is the last time we have to bump the version number by hand. ----------------------------------------------------------------------------------- Changed over to RCS source control here: Version Numbers are reset at this point back to Version 1.1. ----------------------------------------------------------------------------------- RCS file: iozone.c,v; Working file: iozone.c head: 1.94 locks: ; strict access list: symbolic names: comment leader: " * " total revisions: 94; selected revisions: 94 description: Initial rcs version of Iozone ---------------------------- Revision 1.94 date: 99/01/18 13:02:57; author: capps; state: Exp; lines added/del: 7/2 Call msync if writer wants sync in timing and terminates early in multi thread test case. ---------------------------- Revision 1.93 date: 99/01/18 11:46:11; author: capps; state: Exp; lines added/del: 309/126 Cleanup for include_flush and include_close for single and multi threaded operations. ---------------------------- Revision 1.92 date: 99/01/15 10:53:58; author: capps; state: Exp; lines added/del: 40/11 Add include_close support for throughput testing ---------------------------- Revision 1.91 date: 98/12/07 09:26:22; author: capps; state: Exp; lines added/del: 43/24 For Windows: Use the high resolution timers instead of timeofday(); Fix a few casting problems. ---------------------------- Revision 1.90 date: 98/11/30 14:49:46; author: capps; state: Exp; lines added/del: 24/17 Update the copyright and names and places ---------------------------- Revision 1.89 date: 98/10/30 09:04:51; author: capps; state: Exp; lines added/del: 1/2 An extra close(fd) causes HP-UX to fail future unmounts... ---------------------------- Revision 1.88 date: 98/10/29 09:47:25; author: capps; state: Exp; lines added/del: 17/17 Cleanup the help screen ---------------------------- Revision 1.87 date: 98/10/28 23:31:11; author: capps; state: Exp; lines added/del: 7/6 Spelling error fix. ---------------------------- Revision 1.86 date: 98/10/14 11:21:50; author: capps; state: Exp; lines added/del: 23/68 Unified the time method to only have 2 ways to get time. ---------------------------- Revision 1.85 date: 98/10/14 09:22:09; author: capps; state: Exp; lines added/del: 91/91 Added code to remove the latency of gettimeofday() from the file performance measurements. ---------------------------- Revision 1.84 date: 98/10/12 11:44:50; author: capps; state: Exp; lines added/del: 107/8 Add time resolution output, and fix the divide by zero when the time in a system call turns out to be Zero. This will introduce distortion for machines that have very fast system calls and very poor time resolution. Windows has a 50 Milli second resolution on gettimeofday(). So... to fix it all calls that take less than 50 Milli seconds will be rounded up to cost 50 milliseconds. ---------------------------- Revision 1.83 date: 98/10/06 09:58:16; author: capps; state: Exp; lines added/del: 46/2 Add support for Windows build ---------------------------- Revision 1.82 date: 98/09/23 09:48:02; author: capps; state: Exp; lines added/del: 2/2 Fix bug where -i # was leaving tmp files after throughput test. ---------------------------- Revision 1.81 date: 98/09/23 09:41:12; author: capps; state: Exp; lines added/del: 1/3 Remove debug printf ---------------------------- Revision 1.80 date: 98/09/23 09:29:01; author: capps; state: Exp; lines added/del: 23/1 Add my_nap(). This allows the threads to switch processors to their new bound processor before performing any work. ---------------------------- Revision 1.79 date: 98/09/22 11:57:20; author: capps; state: Exp; lines added/del: 8/8 Change xx back into an int so the modulo will work better. ---------------------------- Revision 1.78 date: 98/09/18 16:27:05; author: capps; state: Exp; lines added/del: 18/15 Remove create in rewrite path. ---------------------------- Revision 1.77 date: 98/08/17 16:44:06; author: capps; state: Exp; lines added/del: 23/1 Fixes for Solaris and the new processor bind feature. ---------------------------- Revision 1.76 date: 98/08/17 16:17:45; author: capps; state: Exp; lines added/del: 1/2 Remove debug code. ---------------------------- Revision 1.75 date: 98/08/17 16:16:15; author: capps; state: Exp; lines added/del: 92/5 Add support for binding procs/threads to cpus. ---------------------------- Revision 1.74 date: 98/08/07 16:51:41; author: capps; state: Exp; lines added/del: 4/3 Add fsync to the fwrite test case when the user specifies -e ---------------------------- Revision 1.73 date: 98/08/07 16:47:38; author: capps; state: Exp; lines added/del: 178/208 Add -c and -e to allow closes and fsyncs to be inside the timing calculations. ---------------------------- Revision 1.72 date: 98/08/06 22:40:15; author: capps; state: Exp; lines added/del: 9/1 Add setvbuf to fwrite and fread tests so that the internal fwrite and fread buffer size is the same as the record size. This is what a well tuned application would do. ---------------------------- Revision 1.71 date: 98/08/06 09:03:06; author: capps; state: Exp; lines added/del: 2/3 Fix fsync filename problem in fwrite_perf_test ---------------------------- Revision 1.70 date: 98/08/05 18:06:41; author: capps; state: Exp; lines added/del: 6/2 Add fsync after fwrite test case so the fread will start with a clean buffer cache and no writes in progress. ---------------------------- Revision 1.69 date: 98/08/03 10:45:49; author: capps; state: Exp; lines added/del: 3/3 Bug fix for -V option not filling the entire buffer. ---------------------------- Revision 1.68 date: 98/07/30 22:11:11; author: capps; state: Exp; lines added/del: 2/3 Fix for solaris ---------------------------- Revision 1.67 date: 98/07/30 22:08:19; author: capps; state: Exp; lines added/del: 2/2 Fix for solaris ---------------------------- Revision 1.66 date: 98/07/30 22:05:02; author: capps; state: Exp; lines added/del: 43/15 Add support for Solaris ---------------------------- Revision 1.65 date: 98/07/01 14:19:19; author: capps; state: Exp; lines added/del: 80/82 Move end_async inside the timing loops as in async I/O it counts. ---------------------------- Revision 1.64 date: 98/06/16 17:04:36; author: capps; state: Exp; lines added/del: 13/2 Correct problem where user specifies pread tests on hpux... which does not support these operations. The test now prints an error message and exits. ---------------------------- Revision 1.63 date: 98/06/16 16:54:22; author: capps; state: Exp; lines added/del: 1/2 Remove exit from auto_test. This allows the message "iozone test complete" to be printed when in auto test mode. ---------------------------- Revision 1.62 date: 98/06/10 10:54:28; author: capps; state: Exp; lines added/del: 175/173 All exit()s now have a unique exit value. ---------------------------- Revision 1.61 date: 98/05/18 13:34:03; author: capps; state: Exp; lines added/del: 17/18 Move .dat file descriptors to global data. Needed to prevent re-opens. ---------------------------- Revision 1.60 date: 98/05/18 13:24:22; author: capps; state: Exp; lines added/del: 6/3 Bug fix. Prevents re-opending .dat files when in auto mode. ---------------------------- Revision 1.59 date: 98/05/08 13:03:02; author: capps; state: Exp; lines added/del: 21/3 Enhance throughput tests to follow the -i test number to run options. ---------------------------- Revision 1.58 date: 98/05/07 14:15:49; author: capps; state: Exp; lines added/del: 109/39 Make VXFS a define in the make command. This makes moving to other targets easier. It removes the binding of HPUX and VXFS. Also, Added -Q to support offset/latency file generation for later use as inputs to plot program. ---------------------------- Revision 1.57 date: 98/05/06 15:09:43; author: capps; state: Exp; lines added/del: 100/27 Add -N to provide results in microseconds per operation. ---------------------------- Revision 1.56 date: 98/05/05 13:23:29; author: capps; state: Exp; lines added/del: 3/10 If the user specifies -i 0 then run both write and rewrite tests. ---------------------------- Revision 1.55 date: 98/04/30 15:19:02; author: capps; state: Exp; lines added/del: 1/1 No change ---------------------------- Revision 1.54 date: 98/04/30 15:09:58; author: capps; state: Exp; lines added/del: 2/2 Unlink the vxfstest when the test fails. ---------------------------- Revision 1.53 date: 98/04/30 13:07:21; author: capps; state: Exp; lines added/del: 7/5 Cleanup help output. ---------------------------- Revision 1.52 date: 98/04/30 12:58:29; author: capps; state: Exp; lines added/del: 21/4 Add async I/O with no bcopy to throughput tests. ---------------------------- Revision 1.51 date: 98/04/29 15:29:29; author: capps; state: Exp; lines added/del: 5/1 Fixes so it will compile on the SGI Origin. ---------------------------- Revision 1.50 date: 98/04/29 11:57:58; author: capps; state: Exp; lines added/del: 5/1 Do not need to limit async ops. Fix is in libasync.c ---------------------------- Revision 1.49 date: 98/04/29 10:45:19; author: capps; state: Exp; lines added/del: 61/3 Add async I/O to throughput testing for writes ---------------------------- Revision 1.48 date: 98/04/28 11:57:13; author: capps; state: Exp; lines added/del: 5/1 Limit max async operations to 60. Beyond this there be dragons. ---------------------------- Revision 1.47 date: 98/04/28 10:16:09; author: capps; state: Exp; lines added/del: 108/21 Completed support for no_bcopy POSIX async I/O in the async_write_no_copy path. This allows write tests to perform async I/O with buffers released when the write is completed. ---------------------------- Revision 1.46 date: 98/04/27 16:58:38; author: capps; state: Exp; lines added/del: 43/10 Add aio_write() to the write and re-write tests. This provides POSIX async I/O for the those tests. ---------------------------- Revision 1.45 date: 98/04/25 09:53:39; author: capps; state: Exp; lines added/del: 3/2 direct_flag is an int. Was a char in one place and an int in another. ---------------------------- Revision 1.44 date: 98/04/25 09:17:42; author: capps; state: Exp; lines added/del: 27/15 More support for vx_direct support in the write path ---------------------------- Revision 1.43 date: 98/04/24 16:33:44; author: capps; state: Exp; lines added/del: 115/77 Move VX_DIRECT to libasync. But keep the VX_DIRECT support also in iozone. So one can use VX_DIRECT with and without async I/O ---------------------------- Revision 1.42 date: 98/04/24 16:20:34; author: capps; state: Exp; lines added/del: 127/60 Move VX_DIRECT to the libasync module. ---------------------------- Revision 1.41 date: 98/04/24 15:50:54; author: capps; state: Exp; lines added/del: 190/7 Add support for VxFS VX_DIRECT Idea is to use VX_DIRECT and POSIX async I/O together ---------------------------- Revision 1.40 date: 98/04/22 16:38:25; author: capps; state: Exp; lines added/del: 5/5 Sppux wants ail_gettimeofday variables to be unsigned int. ---------------------------- Revision 1.39 date: 98/04/22 16:19:50; author: capps; state: Exp; lines added/del: 7/3 Fix -M option not printing cleanly Fix -R in 32 bit mode printing garbage. ---------------------------- Revision 1.38 date: 98/04/22 15:56:02; author: capps; state: Exp; lines added/del: 1/1 Change to only disply revision not full header. ---------------------------- Revision 1.37 date: 98/04/22 15:52:19; author: capps; state: Exp; lines added/del: 1/1 Add RCS Header to support versioning. ---------------------------- Revision 1.36 date: 98/04/22 15:38:26; author: capps; state: Exp; lines added/del: 1/1 fix to bcopy() third arg needs to be size_t for 32 bit mode. ---------------------------- Revision 1.35 date: 98/04/22 09:09:24; author: capps; state: Exp; lines added/del: 17/17 Bug fixes for 64 bit mode on IRIX, and addition on the internal inuse queue to insure that the internal struct_cache_ent structures are not released too early when doing direct I/O (async_read_no_copy). ---------------------------- Revision 1.34 date: 98/04/21 09:31:02; author: capps; state: Exp; lines added/del: 4/0 Fix to eliminate hidden (dot) files that iozone was creating in throughput mode. All files are now visible with ls. ---------------------------- Revision 1.33 date: 98/04/21 08:30:35; author: capps; state: Exp; lines added/del: 7/1 Have Iozone print the compile model used. ---------------------------- Revision 1.32 date: 98/04/20 18:46:02; author: capps; state: Exp; lines added/del: 49/20 Fixes for 32 bit mode. ---------------------------- Revision 1.31 date: 98/04/20 16:57:29; author: capps; state: Exp; lines added/del: 8/8 make sure malloc is called with (size_t) parameter. ---------------------------- Revision 1.30 date: 98/04/20 16:05:08; author: capps; state: Exp; lines added/del: 933/757 Iozone now 64 bit application ---------------------------- Revision 1.29 date: 98/04/20 12:32:25; author: capps; state: Exp; lines added/del: 4/4 Move msync to before munmap so file gets written. ---------------------------- Revision 1.28 date: 98/04/20 10:21:30; author: capps; state: Exp; lines added/del: 2/2 Minor fix for -O flag and -B not working smoothly together. ---------------------------- Revision 1.27 date: 98/04/20 10:17:19; author: capps; state: Exp; lines added/del: 0/0 No change ---------------------------- Revision 1.26 date: 98/04/19 15:11:07; author: capps; state: Exp; lines added/del: 5/5 Remove prime_zbfill. It causes problems with mmap files. ---------------------------- Revision 1.25 date: 98/04/16 15:24:50; author: capps; state: Exp; lines added/del: 228/70 -H is Nastran async I/O with bcopy -k is async I/O without any bcopys ---------------------------- Revision 1.24 date: 98/04/15 16:48:30; author: capps; state: Exp; lines added/del: 22/4 fix to make build on 9.05 and 10.1 ---------------------------- Revision 1.23 date: 98/04/15 15:36:55; author: capps; state: Exp; lines added/del: 9/9 Cleanup some compiler warnings about un-initialized variables. They are not really un-initialized and used but it does generate compiler warnings on some machines. ---------------------------- Revision 1.22 date: 98/04/15 15:32:56; author: capps; state: Exp; lines added/del: 7/7 Need to free the dummyname space a bit later. ---------------------------- Revision 1.21 date: 98/04/15 14:37:05; author: capps; state: Exp; lines added/del: 27/13 Fix to use smaller stack size in thread_ routines. It was causing the SGI to drop core in throughput tests. ---------------------------- Revision 1.20 date: 98/04/14 17:01:19; author: capps; state: Exp; lines added/del: 27/16 Fix a memory leak. In multi_throughput testing shmalloc was getting called for each iteration. This is not needed and causes much to much shm to be allocated. Not broken but definately a pig. ---------------------------- Revision 1.19 date: 98/04/14 15:19:15; author: capps; state: Exp; lines added/del: 2/0 When -k is specified alone this will turn on the POSIX async I/O and set depth to 0. ---------------------------- Revision 1.18 date: 98/04/14 15:00:18; author: capps; state: Exp; lines added/del: 21/20 Fixes to make multi-threaded version run on the SGI Origin. ---------------------------- Revision 1.17 date: 98/04/14 11:55:44; author: capps; state: Exp; lines added/del: 17/11 Add support for -k. When using POSIX async I/O use the buffer specified and do not perform any bcopys. ---------------------------- Revision 1.16 date: 98/04/13 10:22:18; author: capps; state: Exp; lines added/del: 27/380 Add libasync library support ---------------------------- Revision 1.15 date: 98/04/11 12:09:25; author: capps; state: Exp; lines added/del: 1/0 Fix memory leak. Now calls del_cache when ever any calls to async_end happen. This will ensure that there are no outstanding I/Os on the cache that ha ve not been canceled . ---------------------------- Revision 1.14 date: 98/04/11 11:57:10; author: capps; state: Exp; lines added/del: 632/47 Add support for POSIX async I/O testing ---------------------------- Revision 1.13 date: 98/03/31 14:30:15; author: capps; state: Exp; lines added/del: 44/6 Fix support for bsd4_2 and ConvexOS ---------------------------- Revision 1.12 date: 98/03/31 11:26:34; author: capps; state: Exp; lines added/del: 2/2 Bump version number to 2.32 ---------------------------- Revision 1.11 date: 98/03/31 11:20:51; author: capps; state: Exp; lines added/del: 70/6 Add support for SGI IRIX and SGI IRIX64 ---------------------------- Revision 1.10 date: 98/03/27 14:00:47; author: capps; state: Exp; lines added/del: 15/20 Put the bcopy back. It is more represenative of what the real application will do. ---------------------------- Revision 1.9 date: 98/03/27 13:25:02; author: capps; state: Exp; lines added/del: 40/14 Improved mmap file support. Now only have 1 long word from each page touched. This eliminates the overhead of bcopy dominating the results. It also is performing the same work that the non-mmap version does with verify(). ---------------------------- Revision 1.8 date: 98/03/27 10:41:13; author: capps; state: Exp; lines added/del: 10/4 Bug fix. Frewrite was truncating the file. This fix ensures that the Frewrite test opens without trunc. ---------------------------- Revision 1.7 date: 98/03/27 10:16:41; author: capps; state: Exp; lines added/del: 3/3 Fix report to specify stride size as a function of reclen. It did not make sense to output kbytes as the value changes when in auto mode to match the current record length. ---------------------------- Revision 1.6 date: 98/03/26 15:28:15; author: capps; state: Exp; lines added/del: 16/8 Add support for -j option. This allows the user to specify the stride size for the strided file access benchmark. ---------------------------- Revision 1.5 date: 98/03/25 15:27:01; author: capps; state: Exp; lines added/del: 1/1 Fixup help screen to reflect new options ---------------------------- Revision 1.4 date: 98/03/25 15:21:23; author: capps; state: Exp; lines added/del: 1/1 Change the revision number ---------------------------- Revision 1.3 date: 98/03/25 15:20:28; author: capps; state: Exp; lines added/del: 16/1 Fixup support for Linux ---------------------------- Revision 1.2 date: 98/03/25 13:58:05; author: capps; state: Exp; lines added/del: 16/3 Bug fixes for SPP-UX ---------------------------- Revision 1.1 date: 98/03/25 10:43:45; author: capps; state: Exp; Initial revision ============================================================================= RCS file: libasync.c,v; Working file: libasync.c head: 1.39 locks: ; strict access list: symbolic names: comment leader: " * " total revisions: 39; selected revisions: 39 description: Initial version of POSIX async I/O library interface. ---------------------------- Revision 1.39 date: 98/07/30 22:05:21; author: capps; state: Exp; lines added/del: 3/1 Add support for Solaris ---------------------------- Revision 1.38 date: 98/07/07 13:00:39; author: capps; state: Exp; lines added/del: 1/11 Remove extra bcopy in the async_write_no_bcopy path. ---------------------------- Revision 1.37 date: 98/06/11 09:47:58; author: capps; state: Exp; lines added/del: 3/3 Fix syntax error for IRIX ---------------------------- Revision 1.36 date: 98/06/10 10:56:55; author: capps; state: Exp; lines added/del: 10/10 All exit()s now have a unique exit value. ---------------------------- Revision 1.35 date: 98/05/07 14:17:20; author: capps; state: Exp; lines added/del: 2/2 Make VXFS a define in the make command. This makes moving to other targets easier. It removes the binding of HPUX and VXFS. Also, Added -Q to support offset/latency file generation for later use as inputs to plot program. ---------------------------- Revision 1.34 date: 98/04/30 15:19:54; author: capps; state: Exp; lines added/del: 1/3 Remove debug code that breaks 64 bit mode compiled code. ---------------------------- Revision 1.33 date: 98/04/30 13:09:13; author: capps; state: Exp; lines added/del: 2/2 Make retval an int so it can be checked for less than zero. ---------------------------- Revision 1.32 date: 98/04/29 16:49:34; author: capps; state: Exp; lines added/del: 5/11 If overshooting on number of asyncs then terminate the loop and let the next time through pick up the I/O. ---------------------------- Revision 1.31 date: 98/04/29 16:37:49; author: capps; state: Exp; lines added/del: 3/3 Remove debug code ---------------------------- Revision 1.30 date: 98/04/29 15:29:48; author: capps; state: Exp; lines added/del: 3/1 Fixes so it will compile on the SGI Origin. ---------------------------- Revision 1.29 date: 98/04/29 11:56:27; author: capps; state: Exp; lines added/del: 36/10 Work around for bug in POSIX async I/O library ---------------------------- Revision 1.28 date: 98/04/29 11:04:26; author: capps; state: Exp; lines added/del: 1/2 Remove debug code ---------------------------- Revision 1.27 date: 98/04/29 11:02:54; author: capps; state: Exp; lines added/del: 54/27 Added resource shortage paths. ---------------------------- Revision 1.26 date: 98/04/28 18:12:51; author: capps; state: Exp; lines added/del: 1/3 Add async I/O to the throughput tests ---------------------------- Revision 1.25 date: 98/04/28 17:12:40; author: capps; state: Exp; lines added/del: 3/1 fix wait_for_ routine to reset w_tail if item being removed is also the tail. ---------------------------- Revision 1.24 date: 98/04/28 16:14:06; author: capps; state: Exp; lines added/del: 1/3 bug fix. 2 calls to malloc for aligned memory. ---------------------------- Revision 1.23 date: 98/04/28 11:57:39; author: capps; state: Exp; lines added/del: 37/13 Limit max async operations to 60. Beyond this there be dragons. ---------------------------- Revision 1.22 date: 98/04/28 10:17:22; author: capps; state: Exp; lines added/del: 127/42 Completed support for no_bcopy POSIX async I/O in the async_write_no_copy path. This allows write tests to perform async I/O with buffers released when the write is completed. ---------------------------- Revision 1.21 date: 98/04/27 16:59:14; author: capps; state: Exp; lines added/del: 246/9 Add aio_write() to the write and re-write tests. This provides POSIX async I/O for the those tests. ---------------------------- Revision 1.20 date: 98/04/24 16:20:55; author: capps; state: Exp; lines added/del: 15/3 Move VX_DIRECT to the libasync module. ---------------------------- Revision 1.19 date: 98/04/24 15:50:13; author: capps; state: Exp; lines added/del: 42/11 Add support for VxFS VX_DIRECT Idea is to use VX_DIRECT and POSIX async I/O together ---------------------------- Revision 1.18 date: 98/04/24 12:36:42; author: capps; state: Exp; lines added/del: 13/5 Fix some error printfs to match the size of the off_t. ---------------------------- Revision 1.17 date: 98/04/24 12:18:11; author: capps; state: Exp; lines added/del: 7/7 Fixes for LP64 mode. off_t changed to off64_t ---------------------------- Revision 1.16 date: 98/04/24 09:33:32; author: capps; state: Exp; lines added/del: 275/35 Add comments and fix for LP64 model on hpux. ---------------------------- Revision 1.15 date: 98/04/23 16:58:06; author: capps; state: Exp; lines added/del: 167/13 Make libasync large file aware. ---------------------------- Revision 1.14 date: 98/04/22 15:58:45; author: capps; state: Exp; lines added/del: 1/1 Change version to only display rcs version id. ---------------------------- Revision 1.13 date: 98/04/22 15:52:54; author: capps; state: Exp; lines added/del: 1/2 Add RCS version support ---------------------------- Revision 1.12 date: 98/04/22 11:39:35; author: capps; state: Exp; lines added/del: 52/8 Add firewall to prevent in flight changes to the aiocb structure. ---------------------------- Revision 1.11 date: 98/04/22 09:10:36; author: capps; state: Exp; lines added/del: 57/19 Bug fixes for 64 bit mode on IRIX, and addition on the internal inuse queue to insure that the internal struct_cache_ent structures are not released too early when doing direct I/O (async_read_no_copy). ---------------------------- Revision 1.10 date: 98/04/21 09:34:14; author: capps; state: Exp; lines added/del: 18/10 Improve error messages. ---------------------------- Revision 1.9 date: 98/04/20 16:06:21; author: capps; state: Exp; lines added/del: 53/50 Iozone now 64 bit application ---------------------------- Revision 1.8 date: 98/04/20 10:17:59; author: capps; state: Exp; lines added/del: 0/0 no change ---------------------------- Revision 1.7 date: 98/04/17 08:49:16; author: capps; state: Exp; lines added/del: 15/2 Optimization on async operations. Just add one to the end of the list if the list already has more than one item. ---------------------------- Revision 1.6 date: 98/04/17 00:00:30; author: capps; state: Exp; lines added/del: 10/2 Make cancel keep trying until it succeeds. Otherwise transfers after the buffer is freed can occur. ---------------------------- Revision 1.5 date: 98/04/16 16:49:28; author: capps; state: Exp; lines added/del: 49/4 Improve error handling when running machine out of memory. ---------------------------- Revision 1.4 date: 98/04/16 15:26:41; author: capps; state: Exp; lines added/del: 118/28 added async_read_no_copy(). This allows the application to let the library specify the destination buffer and perform the async I/O without unwanted bcopys. ---------------------------- Revision 1.3 date: 98/04/14 11:56:23; author: capps; state: Exp; lines added/del: 36/10 Add supporf for -k. When using POSIX async I/O use the buffer specified and do not perform any bcopys. ---------------------------- Revision 1.2 date: 98/04/13 10:35:20; author: capps; state: Exp; lines added/del: 5/7 Fixup for error path to propagate any small transfers. ---------------------------- Revision 1.1 date: 98/04/13 10:21:23; author: capps; state: Exp; Initial revision ============================================================================= RCS file: makefile,v; Working file: makefile head: 1.20 locks: ; strict access list: symbolic names: comment leader: "# " total revisions: 20; selected revisions: 20 description: Initial version of makefile ---------------------------- Revision 1.20 date: 98/10/06 10:36:22; author: capps; state: Exp; lines added/del: 87/28 Add comments to describe each targets capabilities. ---------------------------- Revision 1.19 date: 98/10/06 09:59:18; author: capps; state: Exp; lines added/del: 3/3 Fix spelling error ---------------------------- Revision 1.18 date: 98/10/06 09:58:29; author: capps; state: Exp; lines added/del: 18/3 Add support for Windows build ---------------------------- Revision 1.17 date: 98/08/17 16:44:56; author: capps; state: Exp; lines added/del: 2/2 Fixes for Solaris ---------------------------- Revision 1.16 date: 98/07/30 22:05:33; author: capps; state: Exp; lines added/del: 20/1 Add support for Solaris ---------------------------- Revision 1.15 date: 98/05/07 14:17:26; author: capps; state: Exp; lines added/del: 13/13 Make VXFS a define in the make command. This makes moving to other targets easier. It removes the binding of HPUX and VXFS. Also, Added -Q to support offset/latency file generation for later use as inputs to plot program. ---------------------------- Revision 1.14 date: 98/04/22 16:02:42; author: capps; state: Exp; lines added/del: 2/0 Add RCS version ids. ---------------------------- Revision 1.13 date: 98/04/22 13:58:54; author: capps; state: Exp; lines added/del: 6/6 For now only build the SGI targets in 32 bit mode. There is some problem with POSIX async I/O and 64 bit apps. ---------------------------- Revision 1.12 date: 98/04/22 12:08:25; author: capps; state: Exp; lines added/del: 3/3 Let the IRIX64 target default to its default compile mode. ---------------------------- Revision 1.11 date: 98/04/22 09:10:54; author: capps; state: Exp; lines added/del: 3/3 Bug fixes for 64 bit mode on IRIX, and addition on the internal inuse queue to insure that the internal struct_cache_ent structures are not released too early when doing direct I/O (async_read_no_copy). ---------------------------- Revision 1.10 date: 98/04/21 09:29:57; author: capps; state: Exp; lines added/del: 17/17 Improve dependencies ---------------------------- Revision 1.9 date: 98/04/20 16:05:48; author: capps; state: Exp; lines added/del: 58/29 Iozone now 64 bit application ---------------------------- Revision 1.8 date: 98/04/20 10:17:44; author: capps; state: Exp; lines added/del: 0/0 *** empty log message *** ---------------------------- Revision 1.7 date: 98/04/16 16:50:11; author: capps; state: Exp; lines added/del: 6/6 Have the SGI build 32 bit app too. ---------------------------- Revision 1.6 date: 98/04/15 16:48:09; author: capps; state: Exp; lines added/del: 5/5 Fix to make build on 9.05 and 10.1 ---------------------------- Revision 1.5 date: 98/04/13 10:22:34; author: capps; state: Exp; lines added/del: 14/6 Add support for libasync library. ---------------------------- Revision 1.4 date: 98/04/11 11:57:34; author: capps; state: Exp; lines added/del: 10/10 AAdd support for POSIX async I/O testing ---------------------------- Revision 1.3 date: 98/03/31 11:21:34; author: capps; state: Exp; lines added/del: 24/0 Add support for SGI IRIX and SGI IRIX64 ---------------------------- Revision 1.2 date: 98/03/25 13:59:18; author: capps; state: Exp; lines added/del: 21/9 Fixes for SPP-UX ---------------------------- Revision 1.1 date: 98/03/25 10:48:21; author: capps; state: Exp; Initial revision ============================================================================= Added support for BIFF file output. Iozone can now write Excel spreadsheet format. This allows one to directly access the Excel spreadsheet without needing to import with tab and space delimited method. Added support for large files and threads for Solaris. Add support for FreeBSD Change default stride value to avoid nodalization with various spindle counts. ============================================================================= Version 3.3: Changed name of processor_bind to ioz_processor_bind to avoid collision with SVR5.4.MP shared library. Removed leading tab on an #ifdef that caused some compilers to get sick. ============================================================================= Version 3.4: Add support for OpenBSD ============================================================================= Version 3.6: Lots of code cleanup. Added support for OSF1 on the DEC Alpha. ============================================================================= Version 3.7: Add support for OSF Version 4. Add timer resolution problem detection. ============================================================================= Add support for OSF Version 5. ============================================================================= Version 3.13: Add support for Linux to use pthreads. ============================================================================= Version 3.16: ============================================================================= Add support for Netbsd Add support for Largefiles and Async I/O to Linux target ============================================================================= Version 3.17: ============================================================================= Removed small model for Linux. In the past Iozone was forced to use a small model for testing Linux as the normal load caused Redhat to panic. Redhat users have told me that the system now works fine with the normal load. They have tested Redhat 6.1 and it no longer panics. ============================================================================= Version 3.18: ============================================================================= Add support for BSDI. Base, largefiles, pthread. No async I/O ============================================================================= Revision 3.19 ============================================================================= date: 2000/03/08 14:47:21; author: capps; state: Exp; lines added/del: 4/1 Add support for getpagesize. This is used when available. ============================================================================= Revision 3.20 ============================================================================= date: 00/04/01 11:04:59; author: capps; state: Exp; lines added/del: 2/2 Fix for multiple filenames and range of threads being used. ============================================================================= Revision 3.21 ============================================================================= date: 00/04/01 11:10:54; author: capps; state: Exp; lines added/del: 3/1 SPPUX does not have getpagesize... ============================================================================= Revision 3.22 ============================================================================= Add support for Linux-ia64 Add support for mmap & normal file I/O mixing. ============================================================================= Revision 3.23 Fixups for IBM AIX. ============================================================================= Revision 3.24 Fixups for BSD 2.7 (New release of BSD that supports O_SYNC) ============================================================================= Revision 3.27 Fixups for Cygnus compiler changes. (Windows targets). With this change Iozone will compile with at least 2 versions of the Cygnus compilers. ============================================================================= Revision 3.28 ============================================================================= Add support for reading and writing while holding lockf() on the file. This turns out to be important aspect of NFS benchmarking. ============================================================================= Revision 3.29 ============================================================================= Change calls to lockf() to calls to fcntl(). This is more portable. ============================================================================= Revision 3.30 ============================================================================= Add support for variable compute cycle time before each I/O operation. This allows one to more accuratly represent a specific application that is doing compute/read/compute/read style operations. ============================================================================= Revision 3.30 through 3.37 ============================================================================= Add support for read and write telemetry files. ============================================================================= Revision 3.40 ============================================================================= Code cleanup for popen() usage in -M path. ============================================================================= Revision 3.41 ============================================================================= Bug fix for ops/sec in rewrite throughput testing. Added average throughput to output in throughput mode. ============================================================================= Revision 3.42 ============================================================================= Bug fix for read and re-read. Usage of un-initialized variable that caused results to be wrong. ============================================================================= Revision 3.43 ============================================================================= Add support for latency plot data for throughput testing. Each child thread/process gets its own data file. ============================================================================= Revision 3.44 ============================================================================= Enhance compatibility of multi-thread/proc latency offsets with telemetry file support. ============================================================================= Revision 3.45 through 3.48 ============================================================================= Added latency/offset plot data files for all throughput tests. ============================================================================= Revision 3.49 ============================================================================= Fixed compile warning for Linux off64_t redefinition. Add Solaris2.6 target with simple build. ============================================================================= Revision 3.50 ============================================================================= Added support for openbsd-threads Cleanup for page size foo. ============================================================================= Revision 3.51, 3.52, 3.53 ============================================================================= Cleanup for new random write testing in throughput mode. Improve perror handling. ============================================================================= Revision 3.54 ============================================================================= Add -g maxfilesize so people will not have to edit the source to test files bigger than 512 Mbytes. ============================================================================= Revision 3.55 ============================================================================= Supports -n and -g to set the min and max file sizes to be used for an auto mode run. ============================================================================= Revision 3.56 ============================================================================= Added support for SCO Unixware SVR5 with gcc compiler ============================================================================= Revision 3.57 ============================================================================= Fixed bug where file locking was not being used when _LARGE_FILE64_SOURCE was defined in read_perf_test. ============================================================================= Revision 3.58 ============================================================================= Added -z option. This is to be used with the -a option. It provides more complete testing for small record sizes when the file sizes are very large. Fixed -a so that the cross-over mechanism works correctly. ============================================================================= Revision 3.59 ============================================================================= Fix a bug where the user specified -R -s but did not specify -a or -r. This caused the Excel report to print a bunch of zeros. ============================================================================= Revision 3.60 ============================================================================= Fix headers in the Excel output when cross over kicks in. ============================================================================= Revision 3.61 ============================================================================= Added -y and -q to set record size range Added command line to output ============================================================================= Revision 3.62 ============================================================================= Put auto cross over back to 16 Meg ============================================================================= Revision 3.63 ============================================================================= Minor code cleanups for error messages ============================================================================= Revision 3.64 ============================================================================= Re-organize the help listing. ============================================================================= Revision 3.65 ============================================================================= Add labels to the latency/offset output files. ============================================================================= Revision 3.66 ============================================================================= Added Randy Dunlap to the list of contributors. Thanks Randy !! ============================================================================= Revision 3.67 ============================================================================= Fix labels when using -R and -i options together. ============================================================================= Revision 3.68 ============================================================================= Code cleanup. No functionality changes. ============================================================================= Revision 3.69 ============================================================================= Prevent mixed modes. Auto and throughput. Added support for the Plus extended options. ============================================================================= Revision 3.70 ============================================================================= Added support for -+u option. Cpu utilization. ============================================================================= Revision 3.71 ============================================================================= Added comment for the support for -+u option. Cpu utilization. ============================================================================= Revision 3.72 ============================================================================= Added network testing mode. -+m (Experimental) Tested: Linux, HP-UX ============================================================================= Revision 3.73 ============================================================================= Added -xflag support for distributed mode. Handle interrupts when in distributed mode. ============================================================================= Revision 3.74 ============================================================================= Add default for REMOTE_SHELL ============================================================================= Revision 3.75 ============================================================================= Code cleanup. ============================================================================= Revision 3.76 ============================================================================= Portability change for shmat(). Added and example of client_list file to the distribution. ============================================================================= Revision 3.77 ============================================================================= Disable CPU utilization in distributed mode. Bug fix for CPU utilization in normal mode. ============================================================================= Revision 3.78 ============================================================================= Fix compatibility with AIX for shmat() ============================================================================= Revision 3.79 ============================================================================= Fix throughput labels when user is selecting specific tests with -i option. ============================================================================= Revision 3.80 ============================================================================= Remove dependency on min() and max(). They are not portable. ============================================================================= Revision 3.81 ============================================================================= Changes for 64bit architectures. Brad Smith. OpenBSD. ============================================================================= Revision 3.83 ============================================================================= Add -+m cluster option to the help list and the list of options. ============================================================================= Revision 3.84 -> 3.88 ============================================================================= Fix file descriptor leak in cluster mode. ============================================================================= Revision 3.89 -> 3.91 ============================================================================= Support for heterogeneous clusters, bug fix for -C ============================================================================= Revision 3.92 ============================================================================= Add a small sleep in the client so the master's terminate message can arrive before the client exits and closes the channel. ============================================================================= Revision 3.93 ============================================================================= Add support for UWIN (Unix for Windows) ============================================================================= Revision 3.94 ============================================================================= Bug fix for client's working dir in cluster mode. ============================================================================= Revision 3.95 ============================================================================= Enable more options in Cluster mode. ============================================================================= Revision 3.96 ============================================================================= Add support for Solaris 8 in 64-bit mode. ============================================================================= Revision 3.97 ============================================================================= Linux demands a function proto for functions that take floats as args. ============================================================================= Revision 3.98 ============================================================================= Changes for Solaris to make their silly compiler eat reasonable function prototypes. (yech !!) ============================================================================= Revision 3.99 ============================================================================= Add protocol version checking for distributed messages. Add support for AIX 5.2 ============================================================================= Revision 3.100 ============================================================================= Fixes for socket ports. Needed to be in network format. ============================================================================= Revision 3.101 ============================================================================= Add support for RSH environment override. ============================================================================= Revision 3.102 ============================================================================= Improve O_DIRECT and VX_DIRECT so that testing is done on the correct file on the correct client. ============================================================================= Revision 3.103 ============================================================================= Code cleanup. ============================================================================= Revision 3.104 ============================================================================= Code cleanup. Bug fix for O_DIRECT in read_perf_test. ============================================================================= Revision 3.105 ============================================================================= Bug fix for TRU64 and OSF where reclen was not getting displayed. ============================================================================= Revision 3.106 ============================================================================= Add -+d file I/O diagnostic mode. ============================================================================= Revision 3.107 ============================================================================= Fixes for the awesome Diagnostics mode. ============================================================================= Revision 3.108 ============================================================================= turn off cdebug Switch child comm to SOCK_STREAM. Avoid UDP fragment problems. ============================================================================= Revision 3.109 ============================================================================= Fix for "disrupt" and Direct I/O. Needs to be page size and aligned. ============================================================================= Revision 3.110 ============================================================================= Cleanup for -Wall to all source files. ============================================================================= Revision 3.111 ============================================================================= Fixes for UWIN compile warnings. ============================================================================= Revision 3.112 ============================================================================= Fixes for Windows compile warnings. do_compute() proto. ============================================================================= Revision 3.113 ============================================================================= Add definition char *dumb for Solaris to alloc_mem() ============================================================================= Revision 3.114 ============================================================================= Code cleanup for AIX. No async support caused warnings. ============================================================================= Revision 3.115 ============================================================================= Fix for Solaris returning short reads() from socket to child_listen. ============================================================================= Revision 3.116 ============================================================================= Add support for Mac OS X ============================================================================= Revision 3.117 ============================================================================= Add code to set the socket buffer window size. Solaris needs this. ============================================================================= Revision 3.118 ============================================================================= Add O_Direct for AIX ============================================================================= Revision 3.119-> 3.120 ============================================================================= Fix some compiler warnings and implement the -+x option for setting the multiplier used for file and record size incrementing. ============================================================================= Revision 3.121 ============================================================================= Add changes from Debian. Add powerpc and sparc. Add changes to fix warning on Irix and Irix64 ============================================================================= Revision 3.122 ============================================================================= Bug fix for cluster mode. Need to bzero buffers before sprintf or sscanf ============================================================================= Revision 3.123 ============================================================================= Bug fix for handling all chars that are transported over messaging. ============================================================================= Revision 3.124 ============================================================================= Simplify the child's debug output mechanism. ============================================================================= Revision 3.125 ============================================================================= Fix for stonewall in cluster mode. ============================================================================= Revision 3.126 ============================================================================= Shrink the client_neutral_command structure so it fits in a single UDP packet. ============================================================================= Revision 3.127 ============================================================================= Improve debug code for cluster mode. ============================================================================= Revision 3.128 ============================================================================= Reduce the message traffic due to master's distribution of STOP. Only one STOP distribution is needed. More can lead to socket buffer overflows. ============================================================================= Revision 3.129 ============================================================================= Bzero structures on the stack before using. No problem seen but it is a possible hole. ============================================================================= Revision 3.130 ============================================================================= Add error checking for the client file contents. ============================================================================= Revision 3.131 ============================================================================= Use prealloc() for HP-UX to create file for use with mmap. ============================================================================= Revision 3.132 ============================================================================= Add random mix mode. ============================================================================= Revision 3.133 ============================================================================= Make a better 32 bit random offset from calling rand()<<16||rand() ============================================================================= Revision 3.134 ============================================================================= Add -+p percentage read option. ============================================================================= Revision 3.135 ============================================================================= Improve the mixed mode distribution algorithm. ============================================================================= Revision 3.136 ============================================================================= Fix auto bug introduced by mixed mode testing. Introduce -+r for O_RSYNC. ============================================================================= Revision 3.137 ============================================================================= Code cleanup for some warnings on IA-64 systems. ============================================================================= Revision 3.138 ============================================================================= Fixes for FreeBSD ============================================================================= Revision 3.139 ============================================================================= Add support for multiple -r and -s options. ============================================================================= Revision 3.140 ============================================================================= Code cleanup for non-ansi builds Add target build to output. ============================================================================= Revision 3.141 ============================================================================= Add speed check code. ============================================================================= Revision 3.142 ============================================================================= Increase maximum threads/procs to 256 ============================================================================= Revision 3.143 ============================================================================= Add contribs and -+t to help splash screen. ============================================================================= Revision 3.144 ============================================================================= Bug fix for Redhat. ============================================================================= Revision 3.145 ============================================================================= Bug fix for when user used -l but failed to use -u too. ============================================================================= Revision 3.146 ============================================================================= Add void to speed_main() for non-ansi compiles. ============================================================================= Revision 3.147 ============================================================================= Add "Test running" So users will know the test is running and not to hit control 'c' too soon. Bug fix in libbif.c do_float() ============================================================================= Revision 3.148 ============================================================================= Turn off some child debug code. ============================================================================= Revision 3.149 ============================================================================= Disable fread and fwrite testing if mmap or async is in use. ============================================================================= Revision 3.150 ============================================================================= Add pread/pwrite to Linux ============================================================================= Revision 3.151 ============================================================================= Handle -EB ============================================================================= Revision 3.152 ============================================================================= Add pread/pwrite throughput testing ============================================================================= Revision 3.153 ============================================================================= Changed second parameter to mmap() to be size_t. AIX needs this. ============================================================================= Revision 3.154 ============================================================================= Add support for madvise(). ============================================================================= Revision 3.155 ============================================================================= Code cleanup. ============================================================================= Revision 3.156 ============================================================================= Fixes for -w -t -R from Veritas ============================================================================= Revision 3.157 ============================================================================= Make madvise() go away for windows. ============================================================================= Revision 3.158 ============================================================================= Permit smaller values for -n and -g ============================================================================= Revision 3.159 ============================================================================= Make initial write in initfile() a page size request. ============================================================================= Revision 3.160 ============================================================================= Stop test if file can not be written. ============================================================================= Revision 3.161 ============================================================================= Special handling for mmap of a file that is opened (O_DIRECT) ============================================================================= Revision 3.162 ============================================================================= Fixup for systems that do not have O_DIRECT. ============================================================================= Revision 3.163 ============================================================================= Simplify the prototype for do_compute() ============================================================================= Revision 3.164 ============================================================================= Zero compute_val inside of loops. ============================================================================= Revision 3.165 ============================================================================= Add support for O_DIRECT for IRIX and IRIX64 ============================================================================= Revision 3.166 ============================================================================= Improve macros and add prototypes. ============================================================================= Revision 3.167 ============================================================================= Improve resolution of get_resolution(). ============================================================================= Revision 3.168 ============================================================================= Changes to support RedHat 9.0. ============================================================================= Revision 3.169 ============================================================================= Special handling of NAME for broken frontend in Cygwin/Windows env. ============================================================================= Revision 3.170 ============================================================================= Add support for the CrayX1 ============================================================================= Revision 3.171 ============================================================================= Remove reference to PAGE_SIZE for linux. This causes problems with SuSe 8. ============================================================================= Revision 3.172 ============================================================================= Fixup for SCO build. ============================================================================= Revision 3.173 ============================================================================= Add -DHAVE_PREAD for Solaris8-64 target. ============================================================================= Revision 3.174 ============================================================================= Code cleanup for Linux ============================================================================= Revision 3.177 ============================================================================= Improve -+d so that each byte is more unique. Improve byte level validation. ============================================================================= Revision 3.178 ============================================================================= Provide byte level error detection with Found char and Expecting Char in -+d mode. ============================================================================= Revision 3.179 ============================================================================= Improve speed of -+d without losing uniqueness of bytes. ============================================================================= Revision 3.180 ============================================================================= Fix so that Windows can use multiple processes. Needed mmap like SCO. ============================================================================= Revision 3.181 ============================================================================= Use malloc() instead of mmap() for threads memory, instead of mmap. ============================================================================= Revision 3.182 ============================================================================= Make CPU utilization use doubles everywhere. ============================================================================= Revision 3.183 ============================================================================= Add support for CPU utilization while in distributed mode. ============================================================================= Revision 3.184 ============================================================================= Make all times relative so multi node can do CPU usage. ============================================================================= Revision 3.185 ============================================================================= Remove unused variables. ============================================================================= Revision 3.186 ============================================================================= Add -+n option to disable re-testing. ============================================================================= Revision 3.187 ============================================================================= Fixup -+n for throughput mode. ============================================================================= Revision 3.188 ============================================================================= Fix Excel output when -+n is used. ============================================================================= Revision 3.189 ============================================================================= Add support for the IBM S390 running Linux. ============================================================================= Revision 3.190 ============================================================================= Cleanup naming conventions for the S390 and fixup a #define. ============================================================================= Revision 3.191 ============================================================================= Add 64 bit compiles for s390x Move BIG_ENDIAN to ZBIG_ENDIAN to avoid header conflicts. ============================================================================= Revision 3.192 ============================================================================= Make random offsets always based on 48 bit random values. ============================================================================= Revision 3.193 ============================================================================= Addition for make random offsets always based on 48 bit random values. ============================================================================= Revision 3.194 ============================================================================= Make rands long longs. ============================================================================= Revision 3.195 ============================================================================= Bug fix for 48 bit rands in bsd4_2 and Windows. ============================================================================= Revision 3.196 ============================================================================= Make big_rand a long long. ============================================================================= Revision 3.197 ============================================================================= Inject Erik's changes for Multi-client Windows. ============================================================================= Revision 3.198 ============================================================================= Change proto version due to changes in Windows -+m support. Add Eric to the contributors list. ============================================================================= Revision 3.199 ============================================================================= Add more Windows support. ============================================================================= Revision 3.200 ============================================================================= Spelling error. ============================================================================= Revision 3.201 ============================================================================= Bug fixes from Erik H. ============================================================================= Revision 3.202 ============================================================================= Reduce usage of shared memory. ============================================================================= Revision 3.203 ============================================================================= Eliminate STUPID warning from the silly compiler. ============================================================================= Revision 3.204 ============================================================================= Changes to remove warnings on BSD. Thanks to Christian Weisgerber ============================================================================= Revision 3.205 ============================================================================= Support for the AMD64 ============================================================================= Revision 3.206 ============================================================================= Add -+k for constant aggregate data set size in throughput mode. ============================================================================= Revision 3.207 ============================================================================= Add pread support for the TRU64 target. Department of Defense in Canada. Add -+q for delay in seconds between tests. ============================================================================= Revision 3.208 ============================================================================= Move variable up, GCC on Solaris was getting a bogus parse error ============================================================================= Revision 3.209 ============================================================================= Add support for -+D (O_DSYNC) mode testing. ============================================================================= Revision 3.210 ============================================================================= Make O_DSYNC conditional. ============================================================================= Revision 3.211 ============================================================================= Add telemetry support for pread/pwrite ============================================================================= Revision 3.212 ============================================================================= Add record locking Add single file, file sharing. ============================================================================= Revision 3.213 ============================================================================= Enhance fill/verify (diag mode) for shared file. ============================================================================= Revision 3.214 ============================================================================= Remove warnings. ============================================================================= Revision 3.215 ============================================================================= Add prototype for mylockr() ============================================================================= Revision 3.216 ============================================================================= Fix prototype for mylockr ============================================================================= Revision 3.217 ============================================================================= Enable options for Windows systems. ============================================================================= Revision 3.218 ============================================================================= Add label to Excel spreadsheet that describes the rows and columns. Add support for Solaris64 with VxFS. Add support for Linux-arm ============================================================================= Revision 3.219 ============================================================================= Add sleep to permit child to get connection up before master does connect. ============================================================================= Revision 3.220 ============================================================================= Improve master connect to child, without delays. ============================================================================= Revision 3.221 ============================================================================= Add -+B Mixed sequential testing. BlueArc request. ============================================================================= Revision 3.222 ============================================================================= Workaround for bug in Cygwin's sscanf ============================================================================= Revision 3.223 ============================================================================= Add transfer size to the output from -Q ============================================================================= Revision 3.224 ============================================================================= Work around for TCP_WAIT in Windows. ============================================================================= Revision 3.225 ============================================================================= Fix for broken rsh on Windows. ============================================================================= Revision 3.226 ============================================================================= Workaround for gcc 3.4. From the folks at Gentoo.org. ============================================================================= Revision 3.227 ============================================================================= Enable -+m and telemetry files. ============================================================================= Revision 3.228 ============================================================================= Make more unique file names for mmap files. ============================================================================= Revision 3.229 ============================================================================= Add -+T time stamps. ============================================================================= Revision 3.230 ============================================================================= Bug fix for -m and validation code. ============================================================================= Revision 3.231 ============================================================================= Add a space to the throughput output dump. ============================================================================= Revision 3.232 ============================================================================= Add another space to the throughput output dump. ============================================================================= Revision 3.233 ============================================================================= Enable shared file with no locking ============================================================================= Revision 3.234 ============================================================================= Add sanity check to validate that open(name, O_CREAT | O_WRONLY | O_TRUNC, 0) does work correctly. This is an NFS client test that detects if the NFS server's local filesystem is broken and fails to support the sequence above correctly. ============================================================================= Revision 3.235 ============================================================================= add a close(fd) to the sanity test. ============================================================================= Revision 3.237 ============================================================================= Transport the -o flag to remote clients. ============================================================================= Revision 3.238 ============================================================================= Fix hang when using HP-UX master, Linux client, ssh buildup. ============================================================================= Revision 3.239 ============================================================================= Add -+h hostname. Permits one to manually set the hostname. For systems with multiple names/NICs. ============================================================================= Revision 3.241 ============================================================================= Add -+h, set hostname, and fix Solaris hang. ============================================================================= Revision 3.242 ============================================================================= Remove the side effect of no-rereads when using -w. Now use -+n for consistancy. ============================================================================= Revision 3.243 ============================================================================= Bug fix for -+k option. ============================================================================= Revision 3.246 ============================================================================= Add the -+U for WIN32 API calls .. Unbuffered I/O. Sony studios. ============================================================================= Revision 3.247 ============================================================================= Add support for -+U with -K (WIN32API calls + Jitter) ============================================================================= Revision 3.248 ============================================================================= Bug fix. -J with -+m not passing compute delay correctly. ============================================================================= Revision 3.249 ============================================================================= Add support for -i 8 when used with -+B (sequential mix) ============================================================================= Revision 3.250 ============================================================================= Change the default pattern. Samba is trying to cheat by special casing IOZONE.tmp, and the pattern of 0xA5. ============================================================================= Revision 3.251 ============================================================================= Make the default pattern random, and based on Iozone version. This is to prevent the hack from Richard Sharpe (in Samba) from special casing Iozone, and lying to the user. ============================================================================= Revision 3.252 ============================================================================= bug fix in pattern gen. ============================================================================= Revision 3.253 ============================================================================= Add -+Z old data set mode. Add -+X constant data for short circuit testing only. ============================================================================= Revision 3.254 ============================================================================= Multi-node changes for new options. (-+Z and -+X) ============================================================================= Revision 3.255 ============================================================================= Add -+K flag for Sony. ============================================================================= Revision 3.256 ============================================================================= Move -+K outside of Windows only. ============================================================================= Revision 3.257 ============================================================================= Simplify percentage calculation ============================================================================= Revision 3.258 ============================================================================= Add error checking for -f and -F in the wrong modes. ============================================================================= Revision 3.259 ============================================================================= Bug fix for pbuffer allocation on remote clients. ============================================================================= Revision 3.260 ============================================================================= Check for max_rec_size when using ranges. -r -r -r ============================================================================= Revision 3.261 ============================================================================= Fix for Debian user bug. -r 1m -n 1m -g 2m gave bogus error. ============================================================================= Revision 3.262 ============================================================================= Bug fix for -k used in conjunction with -t and content validation. ============================================================================= Revision 3.263 ============================================================================= Bug fix for -k used in conjunction with -t and content validation. ============================================================================= Revision 3.264 ============================================================================= Add DragonFly target. ============================================================================= Revision 3.265 ============================================================================= Put PER_VECTOR_OFFSET in for HP-UX ============================================================================= Revision 3.266 ============================================================================= Fix compiler warning messages ============================================================================= Revision 3.267 ============================================================================= Enforce minimum file size of page_size ============================================================================= Revision 3.268 ============================================================================= Minor fixes. ============================================================================= Revision 3.269 ============================================================================= Check fsync and close for errors. ============================================================================= Revision 3.270 ============================================================================= Adding support for testing block devices. Will be done is phases. This is phase 1. (Single threaded mode only) ============================================================================= Revision 3.271 ============================================================================= Adding 4 token support to client_list. Each entry may now contain 4 tokens and the new one is the absolute path to the temp file for testing. ============================================================================= Revision 3.272 Editorial change. ============================================================================= Revision 3.273 Add support for external monitor start & stop for throughput tests. IMON_START and IMON_STOP environmental variables used. ============================================================================= Revision 3.274 ============================================================================= minor change. ============================================================================= Revision 3.275 Bug fix for systems without O_DIRECT. Fall through in switch statement. ============================================================================= Revision 3.276 Fix for -c -t over NFS and initial writer close() when told by another to stop ============================================================================= Revision 3.277 Add Benny Halevy to contributors list. ============================================================================= Revision 3.278 Fix for Cygwin environment. ============================================================================= Revision 3.279 Code cleanup, and add arg to external trigger. ============================================================================= Revision 3.280 Code fixes for macosx ============================================================================= ============================================================================= Revision 3.281 Add support for building with Sun's Studio 11 compiler ============================================================================= Revision 3.283 Bug fix for fread/fwrite with > 2Gig files. ============================================================================= Revision 3.287 Add O_DIRECT for Windows ============================================================================= Revision 3.288 Add -+w dedup testing mode. ============================================================================= Revision 3.289 Make remaining non-dedup data unique. ============================================================================= Revision 3.290 Make non-dedupable more unique. ============================================================================= Revision 3.291 Bug fix for non-dedup. ============================================================================= Revision 3.292 Make random offsets unique, using Knuth shuffle. ============================================================================= Revision 3.292 free memory used for random offset uniqueness. ============================================================================= Revision 3.294 Make unique/random offsets 64bits. ============================================================================= Revision 3.295 Add fallback for random/unique. ============================================================================= Revision 3.296 Make non-dedup region more unique ============================================================================= Revision 3.297 Add -+y ## to set percentage of interior dedup. ============================================================================= Revision 3.298 Add -+y ## to set percentage of interior dedup. ============================================================================= Revision 3.299 Bug fixes for -+w and -+y ============================================================================= Revision 3.300 Minor fix for dedup ============================================================================= Revision 3.302 Adding -+C to set percent of dedupable within a file. ============================================================================= Revision 3.303 bug fix ============================================================================= Revision 3.304 Add solaris to read sync O_RSYNC ============================================================================= Revision 3.305 Add space to avoid field output touching each other. ============================================================================= Revision 3.306 Add check for config file exceeding MAXSTREAMS. ============================================================================= Revision 3.307 Add new contributor's name. ============================================================================= Revision 3.308 Fix type-oh ============================================================================= Revision 3.309 Bug fix. rewrite_rec needed to fill entire buffer, or later stride read will fail. ============================================================================= Revision 3.310 ============================================================================= Add ability for remote clients to return errors to the master and have the master display on output. ============================================================================= Revision 3.311 ============================================================================= fix double reporting of client errors ============================================================================= Revision 3.312 ============================================================================= Eliminate extra file descriptor in fwrite test. ============================================================================= Revision 3.312 ============================================================================= bug fix for barray allocation in -T mode ============================================================================= Revision 3.313 Revision 3.314 Revision 3.315 ============================================================================= Changes from Debian: Retry umount, add fileop for linux-sparc, and fix column width in fileop for faster boxes. ============================================================================= Revision 3.316 Add O_DIRECT support to FreeBSD ============================================================================= Revision 3.317 Fix for defines in FreeBSD ============================================================================= Revision 3.318 Add IMON_SYNC to enable monitor scripts to be run sync. ============================================================================= Revision 3.319 Add directio() for Solaris ============================================================================= Revision 3.320 Add fixes for unresolved references in directio() for Solaris ============================================================================= Revision 3.321 Fix type oh. ============================================================================= Revision 3.322 Fix c++ style comment back to 'C' style comment. ============================================================================= Revision 3.323 Bug fix for check_filenames and large files ============================================================================= Revision 3.324 Replace tripple rand() calls with 64 bit Mersene twister. ============================================================================= Revision 3.325 Add read-only, external file, with no-verify. -+E ============================================================================= Revision 3.325 Permit -+E on dedup files. ============================================================================= Revision 3.327 Permit -+E on random read only testing, on existing file. ============================================================================= Revision 3.328 Add passing master listener's port to remote children if it is not HOST_LIST_PORT ============================================================================= Revision 3.329 Adding Dave Boone's notruncate option -+N ============================================================================= Revision 3.330 Bug fix for Dave's code. ============================================================================= Revision 3.331 Add multi -t ops. Fabrice ============================================================================= Revision 3.332 Added Li Qin's multi dedup set support. -+S # ============================================================================= Revision 3.333 Bug fix for -+S dedup_mseed needs to be an integer ============================================================================= Revision 3.334 Make -+S generate more uniqueness ============================================================================= Revision 3.335 Make -+S generate more uniqueness ============================================================================= Revision 3.336 Make -+S generate more uniqueness ============================================================================= Revision 3.337 Bug fix for -+S ============================================================================= Revision 3.338 Make umount/remount more robust, in the face of server errors. ============================================================================= Revision 3.339 Improve the help string for the -+S option. ============================================================================= Revision 3.340 Add new contributor name. ============================================================================= Revision 3.342 Add support for the programmable interdimensional timer. ============================================================================= Revision 3.343 Bug fix for PIT on remote clients. ============================================================================= Revision 3.344 Bug fix for PIT on remote clients. ============================================================================= Revision 3.345 Have children re-acquire get_resolution. ============================================================================= Revision 3.346 Bug fix for t_range addition. ============================================================================= Revision 3.347 Get rid of a warning. ( An invalid warning, but none the less ) ============================================================================= Revision 3.348 Add more words to the usage warnings and license ============================================================================= Revision 3.349 Remove Ascii dependency for IBM's Z/OS that speaks EBCDIC. ============================================================================= Revision 3.353 Add support for SUA ============================================================================= Revision 3.354 Remove Sanity check so that SMB on Windows, under SUA, works ============================================================================= Revision 3.355 Cache the getaddrinfo call. ============================================================================= Revision 3.356 delete optimization.. bad...Cache the getaddrinfo call. ============================================================================= Revision 3.358 Change pit to use unsigned long longs ============================================================================= Revision 3.359 Add Linux processor affinity ============================================================================= Revision 3.360 Remove UDP usage ============================================================================= Revision 3.361 Increment protocol_version to catch incompat versions. ============================================================================= Revision 3.362 Fixup for new include needed by Solaris10 ============================================================================= Revision 3.363 Patch for Mac errno ============================================================================= Revision 3.364 Patch for Mac printf's ============================================================================= Revision 3.365 Fix Josh's introduction of new Linux warnings. ============================================================================= Revision 3.366 Take sleep(1) out put path, deal with it in error/retry path ============================================================================= Revision 3.367 Add -+z latency histogram logging. ============================================================================= Revision 3.368 Format change for the -+z latency histogram logging. ============================================================================= Revision 3.369 Added -+O Op_rate control. ============================================================================= Revision 3.370 Close race condition with master closing socket to child async reader ============================================================================= Revision 3.371 Add "mygen" generation to the remote children protocol. This prevents zombies from coming back to life and killing future masters. ============================================================================= Revision 3.372 Set Listen(s,100) to Listen(s,MAXSTREAMS) ============================================================================= Revision 3.373 Move lable "again" to outside of cdebug. ============================================================================= Revision 3.374 More fixes for busted crap in Solaris !!! ============================================================================= Revision 3.376 AIX update. They now have errno.h ============================================================================= Revision 3.377 Need errno.h for FreeBSD ============================================================================= Revision 3.379 Need to include errno.h for Cygwin ============================================================================= Revision 3.381 Add SO_LINGER for master_listen and child_listen, so that wind-blows will work like all other systems on the planet. ============================================================================= Revision 3.382 Fix for linger addition ============================================================================= Revision 3.383 Fix for linger addition ============================================================================= Revision 3.384 Fix for linger addition ============================================================================= Revision 3.385 Make linger for all ============================================================================= Revision 3.387 Change sleep() calls, that help connect() to nanosleep() calls. ============================================================================= Revision 3.388 Fixup remainder for nanosleep() ============================================================================= Revision 3.389 Fixup remainder for nanosleep() ============================================================================= Revision 3.390 Add code for pread/pwrite from Ben England (Redhat) ============================================================================= Revision 3.391 Add code for MDEBUG and CDEBUG from Bob England (Redhat) ============================================================================= Revision 3.392 Add code for building HPUX. Errno.h ============================================================================= Revision 3.393 Fixes for Windows (nanosleep doesn't always work ) ============================================================================= Revision 3.394 Fixes for preadv and pwritev from RedHat (Ben Englanc) ============================================================================= Revision 3.395 Add warnings for default switch cases, and exit with value for unknowns. ============================================================================= Revision 3.396 Fix warnings from RedHat patches ============================================================================= Revision 3.397 Bug fix for getopt default case, with bad parameter handed in. ============================================================================= Revision 3.398 Adding thread_read_test and thread_write_test. ============================================================================= Revision 3.401 bug fix for re-write rec. ============================================================================= Revision 3.402 Mods for DragonFly support. ============================================================================= Revision 3.403 Add -+W to permit chid_skew. This permits adding files, and continuing the proper sharing/dedup within each quadrant, within same seed group and with previously existing files that were created with a different number of threads. ============================================================================= Revision 3.404 Fix type-oh in usage message. ============================================================================= Revision 3.405 Reduce CPU consumption in the op_rate control mechanism. ============================================================================= Revision 3.406 Increase buffer size for configuration lines. They might be 700 chars long. ============================================================================= Revision 3.407 Work around for cache_line_size suddenly becoming zero and breaking fetchit() ============================================================================= Revision 3.408 Bug fix for clobbering of buffer. "tfile" needed to be bigger, as its address was loaded into filearray[] and then that was overwritten by the mfflag causing parsed names to get loaded. ============================================================================= Revision 3.409 ============================================================================= Bug fix for using -m in combination with -+d ============================================================================= Revision 3.410 ============================================================================= Bug fix: Improve consistency of use_thread in thread_fread and thread_fwrite. ============================================================================= Revision 3.411 ============================================================================= Compat fix: Move from using macosx to IOZ_macosx, because APPLE started using macosx in Mountain Lion. ============================================================================= Revision 3.412 ============================================================================= Adding -+F flag for trunc before thread_write. Needed by Vangel for thread_mix_test. ============================================================================= Revision 3.413 ============================================================================= Bug fix for -+F flag. ============================================================================= Revision 3.414 ============================================================================= Add Vangel to the contributors list ============================================================================= Revision 3.415 ============================================================================= Minor bug fix for -J option (think time) in the thread_pread_test() ============================================================================= Revision 3.417 ============================================================================= Add -+J option. Include think time (-j #) in throughput calculation ============================================================================= Revision 3.419 ============================================================================= Add better handling of exit values. ============================================================================= Revision 3.420 ============================================================================= Add new contributor to list. ============================================================================= Revision 3.421 ============================================================================= Bug fix from Alp Aker: Patch for a minor issue in IOzone's signal_handler() function: the no_unlink option is respected only for the first member of the dummyfile[] array; the rest of the dummy files are unconditionally deleted, whether or not the '+w' flag has been passed to the program. ============================================================================= Revision 3.422 ============================================================================= Code cleanup. No functional changes. ============================================================================= Revision 3.423 ============================================================================= Improve consistency of Kbytes instead of kbytes, KBytes, kBytes... ============================================================================= Revision 3.424 ============================================================================= Fix for 64 bit and touch_dedup. ============================================================================= Revision 3.425 ============================================================================= Fix for 64 bit and gen_new_buf ============================================================================= Revision 3.427 Adjust formatting so fields don't run together. ============================================================================= Revision 3.428 Adjust formatting so fields don't run together. ============================================================================= Revision 3.429 Add two more characters to array my_port_num. ============================================================================= ============================================================================= Revision 3.430 Adding -+b option for bursty operations. Donated by: Avi Shchislowski ============================================================================= Revision 3.432 Adding NetBSD 64 bit. ============================================================================= Revision 3.434 Adding code from Alexey Skidanov. Pthread burst I/O. ============================================================================= Revision 3.434 Convert calls from atoi() into atoll() for those things that are actually long longs. ============================================================================= Revision 3.436 Code cleanup for casting consistency ============================================================================= Revision 3.442 Code cleanup for casting consistency and *&(^&*( compiler warnings !!! ============================================================================= Revision 3.443 Code cleanup for all of the un-needed void * maddness. ============================================================================= Revision 3.444 Cleanup 64 bit compiles. ============================================================================= Revision 3.445 Some BSD changes to avoid compiler complaints. ============================================================================= Revision 3.446 Some BSD changes to avoid compiler complaints. ============================================================================= Revision 3.447 Make sure we don't have missing prototypes. ============================================================================= Revision 3.448 Add support for building targets with NO_SIGNAL, NO_FORK, NO_SOCKET ============================================================================= Revision 3.449 Add support for building targets with NO_SIGNAL, NO_FORK, NO_SOCKET ============================================================================= Revision 3.450 Fix missing typedef in FreeBSD. ============================================================================= Revision 3.451 Fix typeoh in spelling of DragonFly. ============================================================================= Revision 3.452 Make the sighandler_t change effective for all BSD derivatives. ============================================================================= Revision 3.454 Make the my_sig_t change effective for all BSD derivatives. ============================================================================= Revision 3.455 Unify the usage of __FreeBSD__ ============================================================================= Revision 3.456 Build on BSD 10.3 without warnings. Clang compilers. ============================================================================= Revision 3.457 Build on BSD 10.3 without warnings. Clang compilers. ============================================================================= Revision 3.458 Make more friendly to build on Solaris. ============================================================================= Revision 3.459 Make more friendly to build on Solaris. ============================================================================= Revision 3.460 Make more friendly to build on Solaris. ============================================================================= Revision 3.461 Make more friendly to build on Solaris. ============================================================================= Revision 3.462 Make more friendly to build on Solaris. ============================================================================= Revision 3.463 Make more friendly to build on Solaris. ============================================================================= Revision 3.464 Make more friendly to build on Solaris. ============================================================================= Revision 3.465 Make more friendly to build on Solaris. ============================================================================= Revision 3.466 Fix error messages to use the correct file name from dummyfile[xx] instead of "filename" in the thread tests. ============================================================================= Revision 3.467 Fix compiler warning from Clang on MacOS for mythread_create(). Prototype didn't match the formal function definition. ============================================================================= Revision 3.469 Switch to IOZ_macosx everywhere for compatibility with Mountain Lion. ============================================================================= Revision 3.470 Increase MAXSTREAMS to 1024. Systems have more power today than 20+ years ago. ============================================================================= Revision 3.471 Make -+W -+C -+y use a flag instead of its option value to indiate its usage. ============================================================================= Revision 3.472 Adding -+M (special dedupe layout) Adding -+a (set compression in special layout) Adding -+Q (set dedupe granule size in special layout) ============================================================================= Revision 3.473 no change. ============================================================================= Revision 3.474 Cleanup for Cygwin64 build. ============================================================================= Revision 3.475 Cleanup for Cygwin64 build warnings. ============================================================================= Revision 3.476 Cleanup compiler warnings. ============================================================================= Revision 3.477 Bug fix code in special_gen_new_buf.. ============================================================================= Revision 3.478 Bug fix code in special_gen_new_buf.. More copies of the other bug. ============================================================================= Revision 3.479 Bug fix code in special_gen_new_buf.. needed (*op ==0) in one more line. ============================================================================= Revision 3.480 Add -+R option to specify the file names are in a file. ============================================================================= Revision 3.481 Adding new contributor Sudhir Kumar ============================================================================= Revision 3.482 Fix help menu for -+R option. It does not also use -F Bug fix for case of -H where gcc seems to think the size of long long is != size of off64_t Bug fix for prototype mismatch in async_write_no_copy. ============================================================================= Revision 3.483 Fix nesting of #ifdefs so that Windows lack of support for O_DIRECT presents splash indication. Enable O_DIRECT for Windows builds. ============================================================================= Revision 3.485 Improvements for building under Android ============================================================================= Revision 3.486 Fix compiler warning on Android. ============================================================================= Revision 3.488 Improve the Yates/Knuth method for shuffle. ============================================================================= iozone3_488/src/current/iozone.c0000444000175000017500000253550013573734166016014 0ustar cappscapps/************************************************************************/ /* Original Author: */ /* William Norcott (wnorcott@us.oracle.com) */ /* 4 Dunlap Drive */ /* Nashua, NH 03060 */ /* */ /************************************************************************/ /* Enhancements by: */ /* Don Capps (capps@iozone.org) */ /* 7417 Crenshaw */ /* Plano, TX 75025 */ /* */ /************************************************************************/ /* Copyright 1991, 1992, 1994, 1998, 2000, 2001 William D. Norcott */ /************************************************************************/ /* */ /* Iozone is based on the original work done by William Norrcot. It has */ /* been enhanced so that it provides a more complete filesystem */ /* characterization. */ /* Its purpose is to provide automated filesystem characterization. */ /* Enhancements have been made by: */ /* */ /* Don Capps capps@iozone.org */ /* */ /* Iozone can perform single stream and multi stream I/O */ /* also it now performs read, write, re-read, re-write, */ /* read backwards, read/write random, re-read record, */ /* pread, re-pread, re-pwrite, preadv, re-preadv, pwritev, */ /* stride read, and re-pwritev,mmap, POSIX async I/O, NFS */ /* cluster testing and much more. */ /* */ /* The frontend now uses getopt() and the user can control many more */ /* of the actions. */ /* */ /* */ /************************************************************************/ /* THIS SOFTWARE IS PROVIDED BY DON CAPPS AND THE IOZONE CREW "AS IS */ /* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ /* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A */ /* PARTICULAR PURPOSE ARE DISCLAIMED. */ /* */ /* IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY */ /* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */ /* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */ /* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ /* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER */ /* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR */ /* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE. */ /************************************************************************/ /************************************************************************/ /* For the beginner... */ /* */ /* 1. make linux (linux, hpux, convex, hpux_no_ansi) */ /* 2. type ./iozone -Ra */ /* */ /* Hint: Type make (it will give you a list of valid targets) */ /* */ /************************************************************************/ /* The version number */ #define THISVERSION " Version $Revision: 3.488 $" #if defined(Windows) #define NO_THREADS #endif #if defined(linux) #define _GNU_SOURCE #endif /* Include for Cygnus development environment for Windows */ #if defined (Windows) #include #include #else #if defined(linux) || defined(solaris) || defined(IOZ_macosx) || defined(__AIX__) || defined(__FreeBSD__) || defined(_HPUX_SOURCE) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__) #include #else extern int errno; /* imported for errors */ extern int h_errno; /* imported for errors */ #endif #endif #ifdef NO_FORK #define fork no_fork #endif #include #include #if defined (__LP64__) || defined(OSF_64) || defined(__alpha__) || defined(__arch64__) || defined(_LP64) || defined(__s390x__) || defined(__AMD64__) #define MODE "\tCompiled for 64 bit mode." #define _64BIT_ARCH_ #else #define MODE "\tCompiled for 32 bit mode." #endif #ifndef NO_THREADS #include #endif #ifdef ANDROID #include #define pthread_setaffinity_np(pid, size, cpuset) \ syscall(__NR_sched_setaffinity, (pid_t)pid, (size_t)size, (void *)cpuset) #endif #if defined(HAVE_ANSIC_C) && defined(linux) #include #include #endif #ifdef HAVE_PROTO #include "proto.h" #else int atoi(); int close(); int unlink(); int main(); #if !defined(linux) int wait(); #endif int fsync(); void srand48(); long lrand48(); void create_list(); void init_by_array64(unsigned long long *, unsigned long long ); unsigned long long genrand64_int64(void); #endif #include char *help[] = { " Usage: iozone [-s filesize_kB] [-r record_size_kB] [-f [path]filename] [-h]", " [-i test] [-E] [-p] [-a] [-A] [-z] [-Z] [-m] [-M] [-t children]", " [-l min_number_procs] [-u max_number_procs] [-v] [-R] [-x] [-o]", " [-d microseconds] [-F path1 path2...] [-V pattern] [-j stride]", " [-T] [-C] [-B] [-D] [-G] [-I] [-H depth] [-k depth] [-U mount_point]", " [-S cache_size] [-O] [-L cacheline_size] [-K] [-g maxfilesize_kB]", " [-n minfilesize_kB] [-N] [-Q] [-P start_cpu] [-e] [-c] [-b Excel.xls]", " [-J milliseconds] [-X write_telemetry_filename] [-w] [-W]", " [-Y read_telemetry_filename] [-y minrecsize_kB] [-q maxrecsize_kB]", " [-+u] [-+m cluster_filename] [-+d] [-+x multiplier] [-+p # ]", " [-+r] [-+t] [-+X] [-+Z] [-+w percent dedupable] [-+y percent_interior_dedup]", " [-+C percent_dedup_within] [-+a zero_pct] [-+Q dedup granule size]", " [-+M dedup+compress flag ]", " ", " -a Auto mode", " -A Auto2 mode", " -b Filename Create Excel worksheet file", " -B Use mmap() files", " -c Include close in the timing calculations", " -C Show bytes transferred by each child in throughput testing", " -d # Microsecond delay out of barrier", " -D Use msync(MS_ASYNC) on mmap files", " -e Include flush (fsync,fflush) in the timing calculations", " -E Run extension tests", " -f filename to use", " -F filenames for each process/thread in throughput test", " -g # Set maximum file size (in kBytes) for auto mode (or #m or #g)", " -G Use msync(MS_SYNC) on mmap files", " -h help", " -H # Use POSIX async I/O with # async operations", " -i # Test to run (0=write/rewrite, 1=read/re-read, 2=random-read/write", " 3=Read-backwards, 4=Re-write-record, 5=stride-read, 6=fwrite/re-fwrite", " 7=fread/Re-fread, 8=random_mix, 9=pwrite/Re-pwrite, 10=pread/Re-pread", " 11=pwritev/Re-pwritev, 12=preadv/Re-preadv)", " -I Use VxFS VX_DIRECT, O_DIRECT,or O_DIRECTIO for all file operations", " -j # Set stride of file accesses to (# * record size)", " -J # milliseconds of compute cycle before each I/O operation", " -k # Use POSIX async I/O (no bcopy) with # async operations", " -K Create jitter in the access pattern for readers", " -l # Lower limit on number of processes to run", " -L # Set processor cache line size to value (in bytes)", " -m Use multiple buffers", " -M Report uname -a output", " -n # Set minimum file size (in kBytes) for auto mode (or #m or #g)", " -N Report results in microseconds per operation", " -o Writes are synch (O_SYNC)", " -O Give results in ops/sec.", " -p Purge on", " -P # Bind processes/threads to processors, starting with this cpu", " -q # Set maximum record size (in kBytes) for auto mode (or #m or #g)", " -Q Create offset/latency files", " -r # record size in Kb", " or -r #k .. size in kB", " or -r #m .. size in MB", " or -r #g .. size in GB", " -R Generate Excel report", " -s # file size in Kb", " or -s #k .. size in kB", " or -s #m .. size in MB", " or -s #g .. size in GB", " -S # Set processor cache size to value (in kBytes)", " -t # Number of threads or processes to use in throughput test", " -T Use POSIX pthreads for throughput tests", " -u # Upper limit on number of processes to run", " -U Mount point to remount between tests", " -v version information", " -V # Verify data pattern write/read", " -w Do not unlink temporary file", " -W Lock file when reading or writing", " -x Turn off stone-walling", " -X filename Write telemetry file. Contains lines with (offset reclen compute_time) in ascii", " -y # Set minimum record size (in kBytes) for auto mode (or #m or #g)", " -Y filename Read telemetry file. Contains lines with (offset reclen compute_time) in ascii", " -z Used in conjunction with -a to test all possible record sizes", " -Z Enable mixing of mmap I/O and file I/O", " -+b #,# burst size (KB),sleep between burst (mili-second)", " -+E Use existing non-Iozone file for read-only testing", " -+F Truncate file before write in thread_mix_test", " -+J Include think time (-j #) in throughput calculation", " -+K Sony special. Manual control of test 8.", " -+m Cluster_filename Enable Cluster testing", " -+d File I/O diagnostic mode. (To troubleshoot a broken file I/O subsystem)", " -+u Enable CPU utilization output (Experimental)", " -+x # Multiplier to use for incrementing file and record sizes", " -+p # Percentage of mix to be reads", " -+r Enable O_RSYNC|O_SYNC for all testing.", " -+t Enable network performance test. Requires -+m ", " -+n No retests selected.", " -+k Use constant aggregate data set size.", " -+q Delay in seconds between tests.", " -+l Enable record locking mode.", " -+L Enable record locking mode, with shared file.", " -+B Sequential mixed workload.", #if defined(O_DSYNC) " -+D Enable O_DSYNC mode.", #endif #ifndef NO_MADVISE " -+A # Enable madvise. 0 = normal, 1=random, 2=sequential", " 3=dontneed, 4=willneed", #endif " -+N Do not truncate existing files on sequential writes.", " -+S # Dedup-able data is limited to sharing within each numerically", " identified file set.", " -+W # Add this value to the child thread ID, so that additional files", " can be added while maintaining the proper dedupability with previously", " existing files that are within the same seed group (-+S).", " -+V Enable shared file. No locking.", #if defined(Windows) " -+U Windows Unbufferd I/O API (Very Experimental)", #endif " -+X Enable short circuit mode for filesystem testing ONLY", " ALL Results are NOT valid in this mode.", " -+Z Enable old data set compatibility mode. WARNING.. Published", " hacks may invalidate these results and generate bogus, high", " values for results.", " -+w ## Percent of dedup-able data in buffers.", " -+y ## Percent of dedup-able within & across files in buffers.", " -+C ## Percent of dedup-able within & not across files in buffers.", " -+a ## Percent of data that is compressible.", " -+Q ## Dedup granule size.", " -+H Hostname Hostname of the PIT server.", " -+P Service Service of the PIT server.", " -+z Enable latency histogram logging.", " -+M Enable Dedup+compress option. (Experimental).", " -+R enable iozone to take filenames from a file.", "" }; char *head1[] = { " 'Iozone' Filesystem Benchmark Program", " ", THISVERSION, MODE, " ", " Original Author: William Norcott (wnorcott@us.oracle.com)", " 4 Dunlap Drive", " Nashua, NH 03060", " ", " Enhancements: Don Capps (capps@iozone.org)", " 7417 Crenshaw", " Plano, TX 75025", " ", " Copyright 1991, 1992, 1994, 1998, 1999, 2002 William D. Norcott", " ", " License to freely use and distribute this software is hereby granted ", " by the author, subject to the condition that this copyright notice ", " remains intact. The author retains the exclusive right to publish ", " derivative works based on this work, including, but not limited to, ", " revised versions of this work", " ", " Other contributors:", " ", " Don Capps (Network Appliance) capps@iozone.org", " ", ""}; /****************************************************************** INCLUDE FILES (system-dependent) ******************************************************************/ #include #include #include #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(solaris) || defined(Windows) #ifndef my_sig_t typedef void (*my_sig_t)(int); #endif #endif #include #include #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__APPLE__) && !defined(__DragonFly__) #include #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__NetBSD__) #include #include #endif #if defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) || defined(__DragonFly__) #ifndef O_SYNC #define O_SYNC O_FSYNC #endif #endif #if defined (__FreeBSD__) || defined(__DragonFly__) #ifndef O_RSYNC #define O_RSYNC O_FSYNC #endif #endif #if ((defined(solaris) && defined(__LP64__)) || defined(__s390x__)) /* If we are building for 64-bit Solaris, all functions that return pointers * must be declared before they are used; otherwise the compiler will assume * that they return ints and the top 32 bits of the pointer will be lost, * causing segmentation faults. The following includes take care of this. * It should be safe to add these for all other OSs too, but we're only * doing it for Solaris now in case another OS turns out to be a special case. */ #include #include #ifndef NO_SOCKET #include #endif #include #include #endif #if ( defined(solaris) && defined(studio11) ) #include #include #endif #if defined(OSFV5) || defined(linux) #include #endif #if defined(linux) #include #include #include #endif #ifndef MAP_FAILED #define MAP_FAILED -1 #endif #ifdef generic typedef long long off64_t; #endif #if defined(__FreeBSD__) #define __off64_t_defined typedef off_t off64_t; #endif #if defined(__DragonFly__) #define __off64_t_defined typedef off_t off64_t; #endif #ifndef ANDROID #ifndef solaris #ifndef off64_t #ifndef _OFF64_T #ifndef __AIX__ #ifndef __off64_t_defined #ifndef SCO_Unixware_gcc #ifndef UWIN #ifndef __DragonFly__ #ifndef __FreeBSD__ typedef long long off64_t; #endif #endif #endif #endif #endif #endif #endif #endif #endif #endif #ifdef __AIX__ #include #endif #ifdef VXFS #include #endif #ifdef unix #if defined (__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) \ || defined(_SUA_) #include #endif #include #include #include #ifndef NULL #define NULL 0 #endif #ifndef nolimits #include #endif #endif #ifdef HAVE_ANSIC_C #define VOLATILE volatile #else #define VOLATILE #endif #include #ifdef SHARED_MEM #include #endif #if defined(bsd4_2) && !defined(MS_SYNC) #define MS_SYNC 0 #define MS_ASYNC 0 #endif #if defined(bsd4_4) || defined(__DragonFly__) #define MAP_ANONYMOUS MAP_ANON #endif #if defined(SCO_Unixware_gcc) || defined(solaris) || defined(UWIN) || defined(SCO) #define MAP_FILE (0) #endif #if defined(IRIX) || defined(IRIX64) || defined(Windows) || defined(bsd4_2) || defined(bsd4_4) || defined(SCO) || defined(Solaris) || defined(SCO_Unixware_gcc) long long page_size = 4096; #define GOT_PAGESIZE 1 #elif defined(NBPG) long long page_size = NBPG; #define GOT_PAGESIZE 1 #elif defined(old_linux) #include long long page_size = PAGE_SIZE; #define GOT_PAGESIZE 1 #elif !defined(GOT_PAGESIZE) long long page_size = 4096; /* Used when all else fails */ #endif #ifdef HAVE_PREAD #ifdef HAVE_PREADV #define PVECMAX 16 #ifdef _HPUX_SOURCE #define PER_VECTOR_OFFSET #include struct piovec piov[PVECMAX]; #else #include struct iovec piov[PVECMAX]; #define piov_base iov_base #define piov_len iov_len #endif #endif #endif #define DEDUPSEED 0x2719362 #define MAX_RAND 2147483647L #ifdef NO_SOCKET #define socket no_socket int no_socket(int, int, int); #define accept no_accept int no_accept(int , struct sockaddr *, socklen_t *); #define bind no_bind int no_bind(int, const struct sockaddr *, socklen_t); #define connect no_connect int no_connect(int, const struct sockaddr *, socklen_t); #endif #ifdef NO_SIGNAL #define kill no_kill int no_kill(pid_t, int ); #endif /* * In multi thread/process throughput mode each child keeps track of * statistics and communicates them through various flavors of * shared memory, and via messages. */ struct child_stats { long long flag; /* control space */ long long flag1; /* pad */ float walltime; /* child elapsed time */ float cputime; /* child CPU time */ float throughput; /* Throughput in either kb/sec or ops/sec */ float actual; /* Either actual kb read or # of ops performed */ } VOLATILE *child_stat; /* * Used for cpu time statistics. */ struct runtime { float walltime; float cputime; float cpuutil; }; #ifdef __convex_spp #include #endif #include #include #include /* * Messages the controlling process sends to children. * Internal representation that is arch specific. * This is used when using the network distributed mode. */ struct client_command { char c_host_name[100]; char c_pit_hostname[40]; char c_pit_service[8]; char c_client_name[100]; char c_working_dir[200]; char c_file_name[200]; char c_path_dir[200]; char c_execute_name[200]; char c_write_traj_filename[200]; char c_read_traj_filename[200]; int c_oflag; int c_mfflag; int c_unbuffered; int c_noretest; int c_notruncate; int c_read_sync; int c_jflag; int c_async_flag; int c_k_flag; int c_h_flag; int c_mflag; int c_pflag; int c_stride_flag; int c_verify; int c_sverify; int c_odsync; int c_diag_v; int c_zero_pct; int c_N_special; int c_dedup_granule_size; int c_dedup; int c_dedup_flag; int c_dedup_iflag; int c_dedup_bflag; int c_dedup_interior; int c_dedup_compress; int c_dedup_mseed; int c_chid_skew; int c_hist_summary; int c_op_rate; int c_op_rate_flag; int c_Q_flag; int c_inc_think; int c_L_flag; int c_OPS_flag; int c_mmapflag; int c_mmapasflag; int c_mmapnsflag; int c_mmapssflag; int c_no_copy_flag; int c_include_close; int c_include_flush; int c_disrupt_flag; int c_compute_flag; int c_xflag; int c_MS_flag; int c_mmap_mix; int c_Kplus_flag; int c_stop_flag; int c_w_traj_flag; int c_r_traj_flag; int c_direct_flag; int c_cpuutilflag; int c_seq_mix; int c_del_flag; int c_client_number; int c_command; int c_testnum; int c_no_unlink; int c_no_write; int c_file_lock; int c_rec_lock; int c_Kplus_readers; int c_multiplier; int c_share_file; int c_pattern; int c_version; int c_base_time; int c_num_child; int c_pct_read; int c_advise_op; int c_advise_flag; int c_restf; int c_mygen; long long c_stride; long long c_rest_val; long long c_delay; long long c_purge; long long c_fetchon; long long c_numrecs64; long long c_reclen; long long c_child_flag; long long c_delay_start; long long c_depth; float c_compute_time; }; /* * All data in this is in string format for portability in a * hetrogeneous environment. * * Messages that the master will send to the clients * over the socket. This provides neutral format * so that heterogeneous clusters will work. * This is used when using the network distributed mode. * WARNING !!! This data structure MUST not be bigger * than 1448 bytes or fragmentation will kick your butt. */ struct client_neutral_command { char c_host_name[100]; char c_pit_hostname[40]; char c_pit_service[8]; char c_client_name[100]; char c_working_dir[200]; char c_file_name[200]; char c_path_dir[200]; char c_execute_name[200]; char c_write_traj_filename[200]; char c_read_traj_filename[200]; char c_oflag[2]; char c_mfflag[2]; char c_unbuffered[2]; char c_noretest[2]; char c_notruncate[2]; char c_read_sync[2]; char c_jflag[2]; char c_async_flag[2]; char c_k_flag[2]; char c_h_flag[2]; char c_mflag[2]; char c_pflag[2]; char c_stride_flag[2]; char c_verify[2]; char c_sverify[2]; char c_odsync[2]; char c_diag_v[2]; char c_zero_pct[4]; char c_N_special[4]; char c_dedup_granule_size[8]; char c_dedup[4]; char c_dedup_flag[4]; char c_dedup_iflag[4]; char c_dedup_bflag[4]; char c_dedup_interior[4]; char c_dedup_compress[4]; char c_dedup_mseed[4]; char c_chid_skew[4]; char c_hist_summary[4]; char c_op_rate[4]; char c_op_rate_flag[2]; char c_Q_flag[2]; char c_inc_think[2]; char c_L_flag[2]; char c_OPS_flag[2]; char c_mmapflag[2]; char c_mmapasflag[2]; char c_mmapnsflag[2]; char c_mmapssflag[2]; char c_no_copy_flag[2]; char c_include_close[2]; char c_include_flush[2]; char c_disrupt_flag[2]; char c_compute_flag[2]; char c_stop_flag[2]; char c_xflag[2]; char c_MS_flag[2]; char c_mmap_mix[2]; char c_Kplus_flag[2]; char c_w_traj_flag[2]; /* small int */ char c_r_traj_flag[2]; /* small int */ char c_direct_flag[2]; /* small int */ char c_cpuutilflag[2]; /* small int */ char c_seq_mix[2]; /* small int */ char c_del_flag[2]; /* small int */ char c_stride[10]; /* small long long */ char c_rest_val[10]; /* small long long */ char c_purge[10]; /* very small long long */ char c_fetchon[10]; /* very small long long */ char c_multiplier[10]; /* small int */ char c_share_file[10]; /* small int */ char c_file_lock[10]; /* small int */ char c_rec_lock[10]; /* small int */ char c_Kplus_readers[10]; /* small int */ char c_client_number[20]; /* int */ char c_command[20]; /* int */ char c_testnum[20]; /* int */ char c_no_unlink[4]; /* int */ char c_no_write[4]; /* int */ char c_pattern[20]; /* int */ char c_version[20]; /* int */ char c_base_time[20]; /* int */ char c_num_child[20]; /* int */ char c_pct_read[6]; /* small int */ char c_advise_op[4]; /* small int */ char c_advise_flag[4]; /* small int */ char c_restf[4]; /* small int */ char c_mygen[20]; /* long */ char c_depth[20]; /* small long long */ char c_child_flag[40]; /* small long long */ char c_delay[80]; /* long long */ char c_numrecs64[80]; /* long long */ char c_reclen[80]; /* long long */ char c_delay_start[80]; /* long long */ char c_compute_time[80]; /* float */ }; /* * Messages the clients will send to the master. * Internal representation on each client and the master. * This is used when using the network distributed mode. */ struct master_command { char m_host_name[100]; char m_client_name[100]; char m_stop_flag; int m_client_number; int m_client_error; int m_child_port; int m_child_async_port; int m_command; int m_testnum; int m_version; int m_mygen; float m_throughput; float m_cputime; float m_walltime; float m_actual; long long m_child_flag; }; /* * Messages that the clients will send to the master * over the socket. This provides neutral format * so that heterogeneous clusters will work. * This is used when using the network distributed mode. */ struct master_neutral_command { char m_host_name[100]; char m_client_name[100]; char m_client_number[20]; /* int */ char m_client_error[20]; /* int */ char m_stop_flag[4]; /* char +space */ char m_child_port[20]; /* int */ char m_child_async_port[20]; /* int */ char m_command[20]; /* int */ char m_testnum[20]; /* int */ char m_version[20]; /* int */ char m_mygen[20]; /* int */ char m_throughput[80]; /* float */ char m_cputime[80]; /* float */ char m_walltime[80]; /* float */ char m_actual[80]; /* float */ char m_child_flag[80]; /* long long */ }; /* * Possible values for the commands sent to the master */ #define R_CHILD_JOIN 1 #define R_STAT_DATA 2 #define R_FLAG_DATA 3 /* * Possible values for the master's commands sent to a client * * The R_FLAG_DATA is also used by the master to tell the * client to update its flags. */ #define R_JOIN_ACK 4 #define R_STOP_FLAG 5 #define R_TERMINATE 6 #define R_DEATH 7 /* These are the defaults for the processor. They can be * over written by the command line options. */ #define MY_CACHE_LINE_SIZE 32 #define MY_CACHE_SIZE ( 1024 * 1024 ) #define MEG (1024 * 1024) /* * For stride testing use a prime number to avoid stripe * wrap hitting the same spindle. */ #define STRIDE 17 /************************************************************************/ /* */ /* DEFINED CONSTANTS */ /* */ /* Never add a comment to the end of a #define. Some compilers will */ /* choke and fail the compile. */ /************************************************************************/ /* * Size of buffer for capturing the machine's name. */ #define IBUFSIZE 100 /* * How many I/Os before a non-uniform access. */ #define DISRUPT 100 /* * Set the crossover size. This is where the small transfers * are skipped to save time. There is an option to * disable the skipping. */ #define LARGE_REC 65536 /* Default number of kilobytes in file */ #define KILOBYTES 512 /* Default number of bytes in a record */ #define RECLEN 1024 /* Default size of file in bytes*/ #define FILESIZE (KILOBYTES*1024) /* Default number of records */ #define NUMRECS FILESIZE/RECLEN #ifdef __bsdi__ /* At 8 Meg switch to large records */ #define CROSSOVER (8*1024) /*maximum buffer size*/ #define MAXBUFFERSIZE (8*1024*1024) #else /* At 16 Meg switch to large records */ #define CROSSOVER (16*1024) /* Maximum buffer size*/ #define MAXBUFFERSIZE (16*1024*1024) #endif /* Maximum number of children. Threads/procs/clients */ #define MAXSTREAMS 1024 /* Minimum buffer size */ #define MINBUFFERSIZE 128 /* If things ran way too fast */ #define TOOFAST 10 /* Set the maximum number of types of tests */ #define MAXTESTS 12 /* Default fill pattern for verification */ #define PATTERN get_pattern(); #define PATTERN1 0xBB /* Used for Excel internal tables */ #define MAX_X 100 /* Used for Excel internal tables */ #define MAX_Y 512 #define USAGE "\tUsage: For usage information type iozone -h \n\n" /* Maximum number of characters in filename */ #define MAXNAMESIZE 1000 /* * Define the typical output that the user will see on their * screen. */ #ifdef NO_PRINT_LLD #ifdef HAVE_PREAD #include #if defined(HAVE_PREAD) && defined(HAVE_PREADV) #define CONTROL_STRING2 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s%8s%9s%8s%10s%10s%10s%9s%9s\n" #define CONTROL_STRING3 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s\n" #define CONTROL_STRING4 "%16s%8s%9s%9s%8s%10s\n" #else #define CONTROL_STRING2 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s%8s%9s%8s%10s\n" #define CONTROL_STRING3 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s\n" #define CONTROL_STRING4 "%16s%8s%9s%9s%8s%10s\n" #endif #else #define CONTROL_STRING2 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s\n" #define CONTROL_STRING3 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s\n" #define CONTROL_STRING4 "%16s%8s%9s%9s%8s%10s\n" #endif #endif #ifndef NO_PRINT_LLD #ifdef HAVE_PREAD #include #if defined(HAVE_PREAD) && defined(HAVE_PREADV) #define CONTROL_STRING2 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s%8s%9s%8s%10s%10s%10s%9s%9s\n" #define CONTROL_STRING3 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s\n" #define CONTROL_STRING4 "%16s%8s%9s%9s%8s%10s\n" #else #define CONTROL_STRING2 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s%8s%9s%8s%10s\n" #define CONTROL_STRING3 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s\n" #define CONTROL_STRING4 "%16s%8s%9s%9s%8s%10s\n" #endif #else #define CONTROL_STRING2 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%8s%9s\n" #define CONTROL_STRING3 "%16s%8s%9s%9s%8s%10s%8s %9s%9s %9s %9s%9s%9s%9s%9s\n" #define CONTROL_STRING4 "%16s%8s%9s%9s%8s%10s\n" #endif #endif /* For 'auto mode', these defines determine the number of iterations to perform for both the file size and the record length. */ /* Start with 64 kbyte minimum file size by default */ #define KILOBYTES_START 64 /* Default maximum file size. This is 512 MBytes */ #define KILOBYTES_END (1024*512) /* Default starting record size */ #define RECLEN_START 4096 /* Default maximum record size */ #define RECLEN_END (MAXBUFFERSIZE) /* Multiplier for each itteration on file and record size */ #define MULTIPLIER 2 /* * Assign numeric values to each of the tests. */ #define WRITER_TEST 0 #define READER_TEST 1 #define RANDOM_RW_TEST 2 #define REVERSE_TEST 3 #define REWRITE_REC_TEST 4 #define STRIDE_READ_TEST 5 #define FWRITER_TEST 6 #define FREADER_TEST 7 #define RANDOM_MIX_TEST 8 #ifdef HAVE_PREAD #define PWRITER_TEST 9 #define PREADER_TEST 10 #endif /* HAVE_PREAD */ #ifdef HAVE_PREADV #define PWRITEV_TEST 11 #define PREADV_TEST 12 #endif /* HAVE_PREADV */ #define WRITER_MASK (1 << WRITER_TEST) #define READER_MASK (1 << READER_TEST) #define RANDOM_RW_MASK (1 << RANDOM_RW_TEST) #define RANDOM_MIX_MASK (1 << RANDOM_MIX_TEST) #define REVERSE_MASK (1 << REVERSE_TEST) #define REWRITE_REC_MASK (1 << REWRITE_REC_TEST) #define STRIDE_READ_MASK (1 << STRIDE_READ_TEST) #define FWRITER_MASK (1 << FWRITER_TEST) #define FREADER_MASK (1 << FREADER_TEST) #ifdef HAVE_PREAD #define PWRITER_MASK (1 << PWRITER_TEST) #define PREADER_MASK (1 << PREADER_TEST) #endif /* HAVE_PREAD */ #ifdef HAVE_PREADV #define PWRITEV_MASK (1 << PWRITEV_TEST) #define PREADV_MASK (1 << PREADV_TEST) #endif /* HAVE_PREADV */ /* * child_stat->flag values and transitions */ /* Parent initializes children to HOLD */ #define CHILD_STATE_HOLD 0 /* Child tells master when it's READY */ #define CHILD_STATE_READY 1 /* Parent tells child to BEGIN */ #define CHILD_STATE_BEGIN 2 /* Child tells parent that it's DONE */ #define CHILD_STATE_DONE 3 #define MERSENNE /******************************************************************/ /* */ /* FUNCTION DECLARATIONS */ /* */ /******************************************************************/ /*int pit_gettimeofday( struct timeval *, struct timezone *, char *, char *);*/ static int openSckt( const char *, const char *, unsigned int ); static void pit( int, struct timeval *); void auto_test(); /* perform automatic test series */ static double time_so_far(); /* time since start of program */ static void update_burst_sleep(int, long long, double *); #ifndef NO_THREADS static void count_burst(double* burst_acc_time_sec, long long stream_id); #endif #ifdef HAVE_ANSIC_C float do_compute(float); /* compute cycle simulation */ void begin(off64_t,long long); void record_command_line(int, char **); void show_help(void); /* show development help */ #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(solaris) || defined(Windows) my_sig_t signal_handler(void); /* clean up if user interrupts us */ #else sighandler_t signal_handler(void); /* clean up if user interrupts us */ #endif void auto_test(void); void throughput_test(void); static double time_so_far(void); void fetchit(char *,long long); long long verify_buffer(volatile char *,long long, off64_t, long long, unsigned long long, char ); void purgeit(char *,long long); void prepage(char *,long long); void write_perf_test(off64_t, long long, long long *,long long *); void fwrite_perf_test(off64_t, long long, long long *,long long *); void fread_perf_test(off64_t, long long, long long *, long long *); void read_perf_test(off64_t,long long,long long *,long long *); void mix_perf_test(off64_t,long long,long long *,long long *); void random_perf_test(off64_t,long long, long long *,long long *); void reverse_perf_test(off64_t,long long,long long *,long long *); void rewriterec_perf_test(off64_t ,long long,long long *,long long *); void read_stride_perf_test(off64_t,long long,long long *,long long *); #ifdef HAVE_PREAD void pread_perf_test(off64_t,long long ,long long *,long long *); void pwrite_perf_test(off64_t ,long long ,long long *,long long *); #endif /* HAVE_PREAD */ #ifdef HAVE_PREADV void preadv_perf_test(off64_t ,long long ,long long *,long long *); void pwritev_perf_test(off64_t ,long long ,long long *,long long *); #endif /* HAVE_PREADV */ void store_dvalue(double); void print_header(void); void dump_excel(void); void dump_throughput(void); int sp_start_child_send(char *, int , struct in_addr *); int sp_start_master_listen(int , int ); void dump_report(long long); void dump_times(long long); void Poll(long long); long long l_max(long long,long long); void Kill(long long,long long); long long l_min(long long,long long); void multi_throughput_test(long long,long long); long long mythread_create( void *(*func)(void *),int); int thread_exit(void); void get_resolution(void); #ifndef NO_THREADS pthread_t mythread_self(void); #endif void dump_throughput_cpu(void); char * initfile(int , off64_t ,int ,int ); void mmap_end( char *, long long); void my_nap( int ); void my_unap( unsigned long long ); void get_rusage_resolution(void); static double time_so_far1(void); #ifdef unix static double clk_tck(void); /* Get the clocks per tick for times */ static double utime_so_far(void); /* Return user time in ticks as double */ static double stime_so_far(void); /* Return system time in ticks as double */ static double cputime_so_far(void); /* Return CPU time in seconds as double */ #else #define cputime_so_far(void) time_so_far(void) #endif int start_master_listen(void); void master_listen(int , int ); void child_send(char *, struct master_command *, int ); void master_send(int , char *, struct client_command *, int ); void stop_child_listen(int); void O_stop_child_send(int); void stop_master_listen(int); void stop_master_send(int); int start_child_listen(int); int start_child_listen_async(int); void start_child_listen_loop(void); int child_attach(int, int); void child_listen(int, int); void child_listen_async(int, int); int start_master_send(char *, int, struct in_addr *); int start_master_send_async(char *, int , struct in_addr ); long long start_child_proc(int ,long long , long long ); int pick_client(int,long long, long long); void become_client(void); void tell_master_stats(int, long long, double, double, float, double, char, long long); void stop_master_listen_loop(void); void tell_master_ready(long long); void wait_for_master_go(long long); void start_master_listen_loop(int); void tell_children_begin(long long); void wait_dist_join(void); int parse_client_line(char *,int); void child_remove_files(int); void terminate_child_async(void); void distribute_stop(void); void send_stop(void); void cleanup_children(void); void cleanup_comm(void); int sp_start_master_send(char *, int , struct in_addr *); int sp_start_child_listen(int, int); void get_date(char *); int get_pattern(void); void alloc_pbuf(void); int check_filename(char *); int gen_new_buf(char *, char *, long, int, int, int, int, int ); int special_gen_new_buf(char *, char *, long, int, int, int, int, int ); void touch_dedup(char *, int ); void init_genrand64(unsigned long long); long long genrand64_int63(void); double genrand64_real1(void); double genrand64_real2(void); double genrand64_real3(void); int pit_gettimeofday( struct timeval *, struct timezone *, char *, char *); #else /* NON ANSI C */ float do_compute(); /* compute cycle simulation */ void begin(); void record_command_line(); void show_help(); #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(solaris) || defined(Windows) my_sig_t signal_handler(); /* clean up if user interrupts us */ #else sighandler_t signal_handler(); /* clean up if user interrupts us */ #endif void auto_test(); void throughput_test(); static double time_so_far(); void fetchit(); /* Prime on chip cache */ long long verify_buffer(); void purgeit(); /* Purge on chip cache */ void prepage(); /* Pre-fault user buffer */ void write_perf_test(); /* write/rewrite test */ void fwrite_perf_test(); /* fwrite/refwrite test */ void fread_perf_test(); /* fread/refread test */ void read_perf_test(); /* read/reread test */ void mix_perf_test(); /* read/reread test */ void random_perf_test(); /* random read/write test */ void reverse_perf_test(); /* reverse read test */ void rewriterec_perf_test(); /* rewrite record test */ void read_stride_perf_test(); /* read with stride test */ #ifdef HAVE_PREAD void pread_perf_test(); /* pread/re-pread test */ void pwrite_perf_test(); /* pwrite/re-pwrite test */ #endif /* HAVE_PREAD */ #ifdef HAVE_PREADV void preadv_perf_test(); /* preadv/re-preadv test */ void pwritev_perf_test(); /* pwritev/re-pwritev test */ #endif /* HAVE_PREADV */ void store_dvalue(); /* Store doubles array */ void print_header(); void dump_excel(); void dump_throughput(); int sp_start_child_send(); int sp_start_master_listen(); void dump_report(); void dump_times(); void Poll(); long long l_max(); void Kill(); long long l_min(); void multi_throughput_test(); /* Multi process throughput */ long long mythread_create(); int thread_exit(); #ifndef NO_THREADS pthread_t mythread_self(); #endif void dump_throughput_cpu(); char * initfile(); void mmap_end(); void my_nap(); void my_unap(); void get_resolution(); void get_rusage_resolution(); static double time_so_far1(); /* time since start of program */ #ifdef unix static double clk_tck(); /* Get clocks/tick */ static double utime_so_far(); /* user time */ static double stime_so_far(); /* system time */ static double cputime_so_far(); #else #define cputime_so_far() time_so_far() #endif int start_master_listen(); void master_listen(); void child_send(); void master_send(); void stop_child_listen(); void O_stop_child_send(); void stop_master_listen(); void stop_master_send(); int start_child_listen(); int start_child_listen_async(); void start_child_listen_loop(); int child_attach(); void child_listen(); void child_listen_async(); int start_master_send(); int start_master_send_async(); long long start_child_proc(); int pick_client(); void become_client(); void tell_master_stats(); void stop_master_listen_loop(); void tell_master_ready(); void wait_for_master_go(); void start_master_listen_loop(); void tell_children_begin(); void wait_dist_join(); int parse_client_line(); void child_remove_files(); void terminate_child_async(); void distribute_stop(); void send_stop(); void cleanup_children(); void cleanup_comm(void); int sp_start_master_send(char *, int , struct in_addr *); int sp_start_child_listen(int, int); void get_date(); int get_pattern(); void alloc_pbuf(); int check_filename(); int gen_new_buf(); int special_gen_new_buf(); void touch_dedup(); void init_genrand64(); long long genrand64_int63(); double genrand64_real1(); double genrand64_real2(); double genrand64_real3(); int pit_gettimeofday(); #endif /* End of HAVE ANSI C */ #ifdef HAVE_ANSIC_C #if defined (HAVE_PREAD) && defined(_LARGEFILE64_SOURCE) ssize_t pwrite64(); ssize_t pread64(); #endif #if !defined(linux) char *getenv(); char *inet_ntoa(); int system(); #endif #ifdef ASYNC_IO size_t async_write(); void async_release(); int async_read(); int async_read_no_copy(); size_t async_write_no_copy(); void end_async(); void async_init(); #else int async_read(); int async_read_no_copy(); size_t async_write(); size_t async_write_no_copy(); void async_release(); #endif void do_float(); int create_xls(); void close_xls(); void do_label(); int mylockf(int, int, int); int mylockr(int,int, int, off64_t, off64_t); int rand(void); void srand(unsigned int); int get_client_info(void); void exit(int); void find_remote_shell(char *); void find_external_mon(char *,char *); void start_monitor(char *); void stop_monitor(char *); void takeoff_cache(); void del_cache(); void fill_area(long long *, long long *, long long); void fill_buffer(char *,long long ,long long ,char, long long ); void store_value(off64_t); void store_times(double, double); static double cpu_util(double, double); void dump_cputimes(void); void purge_buffer_cache(void); char *alloc_mem(long long,int); void *(thread_rwrite_test)(int); void *(thread_write_test)(int); void *(thread_fwrite_test)(int); void *(thread_fread_test)(int); void *(thread_read_test)(int); #ifdef HAVE_PREAD void *(thread_pread_test)(int); void *(thread_pwrite_test)(int); #endif void *(thread_cleanup_test)(int); void *(thread_cleanup_quick)(int); void *(thread_ranread_test)(int); void *(thread_mix_test)(int); void *(thread_ranwrite_test)(int); void *(thread_rread_test)(int); void *(thread_reverse_read_test)(int); void *(thread_stride_read_test)(int); void *(thread_set_base)(int); void *(thread_join)(long long, void *); void disrupt(int); #if defined(Windows) void disruptw(HANDLE); #endif long long get_traj(FILE *, long long *, float *, long); void create_temp(off64_t, long long ); FILE *open_w_traj(void); FILE *open_r_traj(void); void traj_vers(void); void r_traj_size(void); long long w_traj_size(void); void init_file_sizes(); off64_t get_next_file_size(off64_t); void add_file_size(off64_t); void init_file_sizes( off64_t, off64_t); off64_t get_next_record_size(off64_t); void add_record_size(off64_t); void init_record_sizes( off64_t, off64_t); void del_record_sizes( void ); void hist_insert(double ); void dump_hist(char *,int ); void do_speed_check(int); #else void do_speed_check(); #if !defined(linux) char *getenv(); char *inet_ntoa(); int system(); #endif void close_xls(); void do_label(); int create_xls(); void do_float(); #ifdef ASYNC_IO void async_release(); size_t async_write(); size_t async_write_no_copy(); int async_read(); int async_read_no_copy(); #endif int mylockf(); int mylockr(); int rand(); void srand(); int get_client_info(); void exit(); void find_remote_shell(); void traj_vers(); void r_traj_size(); long long w_traj_size(); FILE *open_w_traj(); FILE *open_r_traj(); void create_temp(); void fill_buffer(); char *alloc_mem(); void *(thread_rwrite_test)(); void *(thread_write_test)(); void *(thread_fwrite_test)(); void *(thread_fread_test)(); void *(thread_read_test)(); void *(thread_cleanup_test)(); void *(thread_ranread_test)(); void *(thread_mix_test)(); void *(thread_ranwrite_test)(); void *(thread_rread_test)(); void *(thread_reverse_read_test)(); void *(thread_stride_read_test)(); void *(thread_set_base)(); void *(thread_join)(); void disrupt(); long long get_traj(); void init_file_sizes(); off64_t get_next_file_size(); void add_file_size(); void init_record_sizes(); off64_t get_next_record_size(); void add_record_size(); void dump_cputimes(); static double cpu_util(); void del_record_sizes(); void hist_insert(); void dump_hist(); #endif #ifdef _LARGEFILE64_SOURCE #define I_LSEEK(x,y,z) lseek64(x,(off64_t)(y),z) #define I_OPEN(x,y,z) open64(x,(int)(y),(int)(z)) #define I_CREAT(x,y) creat64(x,(int)(y)) #define I_FOPEN(x,y) fopen64(x,y) #define I_STAT(x,y) stat64(x,y) #ifdef HAVE_PREAD #define I_PREAD(a,b,c,d) pread64(a,b,(size_t)(c),(off64_t)(d)) #define I_PWRITE(a,b,c,d) pwrite64(a,b,(size_t)(c),(off64_t)(d)) #endif #define I_MMAP(a,b,c,d,e,f) mmap64((void *)(a),(size_t)(b),(int)(c),(int)(d),(int)(e),(off64_t)(f)) #else #define I_LSEEK(x,y,z) lseek(x,(off_t)(y),z) #define I_OPEN(x,y,z) open(x,(int)(y),(int)(z)) #define I_CREAT(x,y) creat(x,(int)(y)) #define I_FOPEN(x,y) fopen(x,y) #define I_STAT(x,y) stat(x,y) #ifdef HAVE_PREAD #define I_PREAD(a,b,c,d) pread(a,b,(size_t)(c),(off_t)(d)) #define I_PWRITE(a,b,c,d) pwrite(a,b,(size_t)(c),(off_t)(d)) #endif #define I_MMAP(a,b,c,d,e,f) mmap((void *)(a),(size_t)(b),(int)(c),(int)(d),(int)(e),(off_t)(f)) #endif /************************************************************************/ /* The list of tests to be called. */ /************************************************************************/ void (*func[])() = { write_perf_test, read_perf_test, random_perf_test, reverse_perf_test, rewriterec_perf_test, read_stride_perf_test, fwrite_perf_test, fread_perf_test, mix_perf_test #ifdef HAVE_PREAD , pwrite_perf_test, pread_perf_test #ifdef HAVE_PREADV , pwritev_perf_test, preadv_perf_test #endif /* HAVE_PREADV */ #endif /* HAVE_PREAD */ }; /* char *test_output[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " \n" }; */ #ifdef FOOBAR random random bkwd record stride write rewrite read reread read write read rewrite read fwrite frewrite fread freread pwv prwv prv prrv #endif char *test_output[] ={" ", " ", " ", " ", " ", " ", " ", " ", "", " ", " ", " ", " ", " ", " ", " \n" }; long long test_soutput[] = {2,2,2,1,1,1,2,2,2,2,2,2,2,2}; /******************************************************************/ /* */ /* GLOBAL VARIABLES */ /* */ /*******************************************************************/ /* * Set the size of the shared memory segment for the children * to put their results. */ #define SHMSIZE ((( sizeof(struct child_stats) * MAXSTREAMS) )+4096 ) /* * Pointer to the shared memory segment. */ VOLATILE struct child_stats *shmaddr; double totaltime,total_time, temp_time ,total_kilos; off64_t report_array[MAX_X][MAX_Y]; double report_darray[MAX_X][MAXSTREAMS]; double time_res,cputime_res; long long throughput_array[MAX_X]; /* Filesize & record size are constants */ short current_x, current_y; long long orig_size; long long max_x, max_y; unsigned long long goodkilos; off64_t kilobytes64 = (off64_t)KILOBYTES; long long goodrecl; off64_t offset = 0; /*offset for random I/O */ off64_t offset64 = 0; /*offset for random I/O */ off64_t filebytes64; off64_t r_range[100]; off64_t s_range[100]; int t_range[100]; int t_count = 0; int r_count,s_count; char *barray[MAXSTREAMS]; char *haveshm; #if !defined(Windows) extern int optind; #endif long long onetime, auto_mode, sfd, multi_buffer; int exit_code = 0; int fd; int sp_msfd,sp_mrfd,sp_csfd,sp_crfd; int begin_proc,num_processors,ioz_processor_bind; long long res_prob,rec_prob; char silent,read_sync; char master_iozone, client_iozone,distributed; int bif_fd,s_count; int bif_row,bif_column; int dedup_mseed = 1; int chid_skew = 0; int hist_summary; int op_rate; int op_rate_flag; char aflag, Eflag, hflag, Rflag, rflag, sflag,del_flag,mix_test; char diag_v,sent_stop,dedup,dedup_interior,dedup_compress, dedup_flag, dedup_iflag,dedup_bflag; int zero_pct = -1; int N_special = 0; int W_special = 0; int dedup_granule_size = 4096; int dedup_unit_step = 1024; char *dedup_ibuf; char *dedup_temp; char bif_flag; int rlocking; int share_file; int ecount; char gflag,nflag; char yflag,qflag; #ifdef Windows char *build_name = "Windows"; #else char *build_name = NAME; #endif char imon_start[256],imon_stop[256]; char imon_sync; char trflag; char cpuutilflag; char seq_mix; long base_time; long long mint, maxt; long long w_traj_ops, r_traj_ops, w_traj_fsize,r_traj_fsize; long long r_traj_ops_completed,r_traj_bytes_completed; long long w_traj_ops_completed,w_traj_bytes_completed; int w_traj_items, r_traj_items; char fflag, Uflag,uflag,lflag,include_tflag; struct runtime runtimes [MAX_X] [MAX_Y]; /* in parallel with report_array[][] */ long long include_test[50]; long long include_mask; char RWONLYflag, NOCROSSflag; /*auto mode 2 - kcollins 8-21-96*/ char mfflag,F_flag; long long status, x, y, childids[MAXSTREAMS+1], myid, num_child; int pct_read,speed_code; #ifndef NO_THREADS pthread_t p_childids[MAXSTREAMS+1]; #endif off64_t next64; char wol_opened, rol_opened; FILE *wqfd,*rwqfd,*rqfd,*rrqfd; #if !defined(Windows) extern char *optarg; #endif #ifndef __AIX__ long long ret; #else short ret; #endif struct size_entry { struct size_entry *next; off64_t size; }; struct size_entry *size_list=0; struct size_entry *rec_size_list=0; off64_t maximum_file_size; off64_t minimum_file_size; off64_t burst_size_kb_64 = -1; /* the size of the burst (in KBytes) */ long long burst_sleep_duration_msec = -1; /* the sleep duration between burst */ long long written_this_burst = 0; /* How much data was writen so far in this burst*/ #ifndef NO_THREADS pthread_barrierattr_t barrier_attr; pthread_barrier_t *barrier; off64_t burst_size_per_child = 0; long long burst_written_so_far[MAXSTREAMS] = {0}; /* How much data was written so far in this burst per stream (thread/process)*/ #endif char bif_filename [MAXNAMESIZE]; /* name of biff file */ char filename [MAXNAMESIZE]; /* name of temporary file */ char mountname [MAXNAMESIZE]; /* name of device */ char dummyfile [MAXSTREAMS][MAXNAMESIZE]; /* name of dummy file */ char dummyfile1 [MAXNAMESIZE]; /* name of dummy file */ char *filearray[MAXSTREAMS]; /* array of file names */ int blkidx[MAXSTREAMS]; /* array of file names */ char tfile[MAXNAMESIZE]; char *buffer,*buffer1, *mbuffer,*mainbuffer; FILE *pi,*r_traj_fd,*w_traj_fd; VOLATILE char *pbuffer; char *default_filename="iozone.tmp"; /*default name of temporary file*/ VOLATILE char stoptime; char Cflag; char use_thread = 0; long long debug1=0; long long debug=0; unsigned long cache_size=(long long)MY_CACHE_SIZE; unsigned long cache_line_size=(long long)MY_CACHE_LINE_SIZE; long long *pstatus; off64_t min_file_size = KILOBYTES_START; off64_t max_file_size = KILOBYTES_END; long long min_rec_size = RECLEN_START; long long max_rec_size = RECLEN_END; long long orig_min_rec_size = RECLEN_START; long long orig_max_rec_size = RECLEN_END; long long xover = CROSSOVER; char *throughput_tests[] = {"Initial write","Rewrite","Read","Re-read", "Reverse Read","Stride read","Random read","Mixed workload","Random write","Pwrite","Pread","Fwrite","Fread"}; char command_line[1024] = "\0"; #ifdef unix double sc_clk_tck; #endif int argcsave; char **argvsave; char splash[80][80]; int splash_line; char client_filename[256]; char remote_shell[256]; int client_error; char pit_hostname[40]; char pit_service[8]; int junk; /* * Host ports used to listen, and handle errors. */ #define HOST_LIST_PORT 20000 #define HOST_ESEND_PORT (HOST_LIST_PORT+MAXSTREAMS) #define HOST_ASEND_PORT (HOST_ESEND_PORT+MAXSTREAMS) int controlling_host_port = HOST_LIST_PORT; /* * Childs ports used to listen, and handle errors. */ #define CHILD_ESEND_PORT (HOST_ASEND_PORT+MAXSTREAMS) #define CHILD_LIST_PORT (CHILD_ESEND_PORT+MAXSTREAMS) /* Childs async message port. Used for stop flag and terminate */ #define CHILD_ALIST_PORT (CHILD_LIST_PORT+MAXSTREAMS) /* Ports for the network speed code */ #define SP_CHILD_LISTEN_PORT 31000 #define SP_CHILD_ESEND_PORT (SP_CHILD_LISTEN_PORT+10) #define SP_MASTER_LISTEN_PORT (SP_CHILD_ESEND_PORT+10) #define SP_MASTER_ESEND_PORT (SP_MASTER_LISTEN_PORT+10) #define SP_MASTER_RESULTS_PORT (SP_MASTER_ESEND_PORT+10) #define THREAD_WRITE_TEST 1 #define THREAD_REWRITE_TEST 2 #define THREAD_READ_TEST 3 #define THREAD_REREAD_TEST 4 #define THREAD_STRIDE_TEST 5 #define THREAD_RANDOM_READ_TEST 6 #define THREAD_RANDOM_WRITE_TEST 7 #define THREAD_REVERSE_READ_TEST 8 #define THREAD_RANDOM_MIX_TEST 9 #define THREAD_PWRITE_TEST 10 #define THREAD_PREAD_TEST 11 #define THREAD_FWRITE_TEST 12 #define THREAD_FREAD_TEST 13 #define THREAD_CLEANUP_TEST 14 /* * Child states that the master is tracking. * The master uses these to determine how to shutdown * the clients when some fool hits control-C. */ #define C_STATE_ZERO 1 #define C_STATE_WAIT_WHO 2 #define C_STATE_WAIT_BARRIER 3 int c_port,a_port; /* port number */ int child_port; /* Virtualized due to fork */ int child_async_port; /* Virtualized due to fork */ int client_listen_pid; /* Virtualized due to fork */ int master_join_count; /* How many children have joined */ int l_sock,l_async_sock; /* Sockets for listening */ char master_rcv_buf[4096]; /* Master's receive buffer */ int master_listen_pid; /* Pid of the master's async listener proc */ char master_send_buf[4096]; /* Master's send buffer */ char child_rcv_buf[4096]; /* Child's receive buffer */ char child_async_rcv_buf[4096]; /* Child's async recieve buffer */ char child_send_buf[4096]; /* Child's send buffer */ int child_send_socket; /* Child's send socket */ int child_listen_socket; /* Child's listener socket */ int child_listen_socket_async; /* Child's async listener socket */ int master_send_socket; /* Needs to be an array. One for each child*/ int master_send_sockets[MAXSTREAMS]; /* Needs to be an array. One for each child*/ int master_send_async_sockets[MAXSTREAMS]; /* Needs to be an array. One for each child*/ int master_listen_port; /* Master's listener port number */ int master_listen_socket; /* Master's listener socket */ int clients_found; /* Number of clients found in the client file */ FILE *newstdin, *newstdout, *newstderr; /* used for debug in cluster mode.*/ char toutput[20][20]; /* Used to help format the output */ int toutputindex; /* Index to the current output line */ int cdebug = 0; /* Use to turn on child/client debugging in cluster mode. */ int mdebug = 0; /* Use to turn on master debug in cluster mode */ int aggflag; /* Used to indicate constant aggregate data set size */ struct sockaddr_in child_sync_sock, child_async_sock; /* * Change this whenever you change the message format of master or client. */ int proto_version = 25; /******************************************************************************/ /* Tele-port zone. These variables are updated on the clients when one is */ /* using cluster mode. (-+m) */ /* Do not touch these unless you have become one with the universe !! */ /******************************************************************************/ char controlling_host_name[100]; struct child_ident { char child_name[100]; char workdir[200]; char execute_path[200]; char file_name[200]; int state; int child_number; int child_port; int child_async_port; int master_socket_num; int master_async_socket_num; }child_idents[MAXSTREAMS]; int Kplus_readers; char write_traj_filename [MAXNAMESIZE]; /* name of write telemetry file */ char read_traj_filename [MAXNAMESIZE]; /* name of read telemetry file */ char oflag,jflag,k_flag,h_flag,mflag,pflag,unbuffered,Kplus_flag; char noretest; char notruncate; /* turn off truncation of files */ char async_flag,stride_flag,mmapflag,mmapasflag,mmapssflag,mmapnsflag,mmap_mix; char verify = 1; int restf; char sverify = 1; char odsync = 0; char inc_think, Q_flag,OPS_flag; char L_flag=0; char no_copy_flag,include_close,include_flush; char disrupt_flag,compute_flag,xflag,Z_flag, X_flag; int no_unlink = 0; int no_write = 0; int r_traj_flag,w_traj_flag; int mygen; char MS_flag; int advise_op,advise_flag; int direct_flag; int current_client_number; long long chid; int file_lock; unsigned int pattern; long long stride = STRIDE; long long delay,purge,fetchon; off64_t numrecs64 = (off64_t)NUMRECS; long long reclen = RECLEN; long long delay_start,depth; VOLATILE char *stop_flag; /* Used to stop all children */ float compute_time; int multiplier = MULTIPLIER; long long rest_val; #if defined(Windows) HANDLE hand; #endif /******************************************************************************/ /* End of Tele-port zone. */ /******************************************************************************/ /* * Prototypes * Sort of... Full prototypes break non-ansi C compilers. No protos is * a bit sloppy, so the compromise is this. */ void stop_child_send(); void stop_child_send(); void child_send(); long compressible_rand(void); void new_touch_dedup(char *, int); /****************************************************************/ /* */ /* MAIN () */ /* */ /****************************************************************/ int main(argc,argv) int argc; char **argv; { long long fileindx,i,tval; long long ind; int ret; FILE *pi; char reply[IBUFSIZE]; unsigned char inp_pat; time_t time_run; char *port,*m,*subarg; int num_child1; int cret; int anwser,bind_cpu; char *evalue; strcpy(tfile,"iozone"); /* Dummy name prefix */ anwser=bind_cpu=0; /* Used to make fread/fwrite do something better than their defaults */ setvbuf( stdout, NULL, _IONBF, (size_t) NULL ); setvbuf( stderr, NULL, _IONBF, (size_t) NULL ); /* Save the master's name */ gethostname(controlling_host_name,100); /* Let user activate mdebug or cdebug via environmental variables */ evalue = (char *)NULL; evalue=(char *)getenv("CDEBUG"); if(evalue) cdebug=atoi(evalue); evalue = (char *)NULL; evalue=(char *)getenv("MDEBUG"); if(evalue) mdebug=atoi(evalue); srand(time(0)); mygen=rand(); /* Pick a random generation number */ /* Try to find the actual VM page size, if possible */ #if defined (solaris) || defined (_HPUX_SOURCE) || defined (linux) || defined(IRIX) || defined (IRIX64) || defined(__NetBSD__) #ifndef __convex_spp page_size=getpagesize(); #endif #endif /* Try to find the actual number of ticks per second */ #ifdef unix sc_clk_tck = clk_tck(); #endif for(ind=0;ind 60) depth=60; */ #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tPOSIX Async I/O (no bcopy). Depth %ld \n",depth); #else sprintf(splash[splash_line++],"\tPOSIX Async I/O (no bcopy). Depth %lld \n",(long long)depth); #endif no_copy_flag=1; async_flag++; k_flag++; break; case 'T': /* Switch to POSIX thread based */ #ifndef NO_THREADS use_thread++; #else printf("\tThreads not supported in this version\n"); exit(2); #endif break; case 'H': /* Use POSIX async_io */ h_flag++; depth = (long long)(atoi(optarg)); if(depth <0) depth=0; /* * Hmmm. many systems fail is strange ways when the maximum * number of async I/Os per user or proc is exceeded. */ /* if(depth > 60) depth=60; */ #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tPOSIX async I/O (with bcopy). Depth %ld\n",depth); #else sprintf(splash[splash_line++],"\tPOSIX async I/O (with bcopy). Depth %lld\n",(long long)depth); #endif async_flag++; break; case 'I': /* Use VXFS direct advisory or O_DIRECT from Linux or AIX , or O_DIRECTIO for TRU64 or Solaris directio */ #ifdef VXFS direct_flag++; sprintf(splash[splash_line++],"\tVxFS advanced feature SET_CACHE, VX_DIRECT enabled\n"); break; #endif #if !defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined(__FreeBSD__) || defined(solaris) || defined(IOZ_macosx) direct_flag++; #if defined __APPLE__ && __MACH__ sprintf(splash[splash_line++],"\tF_NOCACHE=1 - Turns data caching off\n"); #else sprintf(splash[splash_line++],"\tO_DIRECT feature enabled\n"); #endif break; #endif #if defined(TRU64) direct_flag++; sprintf(splash[splash_line++],"\tO_DIRECTIO feature enabled\n"); break; #endif #else #if defined(Windows) sprintf(splash[splash_line++],"\tO_DIRECTIO feature not available in Windows version.\n"); #endif break; #endif case 'B': /* Use mmap file for test file */ sprintf(splash[splash_line++],"\tUsing mmap files\n"); mmapflag++; mmapnsflag++; break; case 'D': /* Use async msync mmap file */ sprintf(splash[splash_line++],"\tUsing msync(MS_ASYNC) on mmap files\n"); mmapflag++; mmapasflag++; mmapnsflag=0; break; case 'G': /* Use msync sync for mmap file */ sprintf(splash[splash_line++],"\tUsing msync(MS_SYNC) on mmap files\n"); mmapssflag++; mmapnsflag=0; break; case 'C': /* show children xfer counts */ Cflag++; break; case 'Q': /* Enable output offset/latency files */ sprintf(splash[splash_line++],"\tOffset/latency files enabled.\n"); Q_flag++; break; case 'x': /* Disable stone_wall */ sprintf(splash[splash_line++],"\tStonewall disabled\n"); xflag++; break; case 'a': /* auto mode */ fetchon=1; purge=0; multi_buffer=0; auto_mode = 1; aflag++; sprintf(splash[splash_line++],"\tAuto Mode\n"); break; case 'c': /* Include close in timing */ include_close++; sprintf(splash[splash_line++],"\tInclude close in write timing\n"); break; case 'e': /* Include fsync in timing */ include_flush++; sprintf(splash[splash_line++],"\tInclude fsync in write timing\n"); break; case 'A': /* auto2 mode. Soon to go away. Please use -az */ fetchon=1; purge=0; multi_buffer=0; auto_mode = 1; aflag++; sprintf(splash[splash_line++],"\tAuto Mode 2. This option is obsolete. Use -az -i0 -i1 \n"); RWONLYflag++; NOCROSSflag++; include_tflag++; /* automatically set WRITER_TEST and READER_TEST */ include_test[WRITER_TEST]++; include_test[READER_TEST]++; break; case 's': /* Set file size */ #ifdef NO_PRINT_LLD sscanf(optarg,"%ld",&kilobytes64); #else sscanf(optarg,"%lld",(long long *)&kilobytes64); #endif if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ ; } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ kilobytes64 = kilobytes64 * 1024; } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ kilobytes64 = kilobytes64 *1024 * 1024; } if(kilobytes64 <= 0) kilobytes64=512; s_range[s_count++]=kilobytes64; max_file_size = (off64_t)s_range[s_count-1]; /* Make visable globally */ min_file_size = (off64_t)s_range[0]; /* Make visable globally */ #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tFile size set to %ld kB\n",(long long)kilobytes64); #else sprintf(splash[splash_line++],"\tFile size set to %lld kB\n",(long long)kilobytes64); #endif sflag++; break; case 'l': /* Set lower thread/proc limit */ mint = (long long)(atoi(optarg)); if(mint <= 0) { mint=1; num_child=1; }else num_child=mint; if(mint > (long long)MAXSTREAMS){ printf("Invalid options: maximum streams for "); printf("throughput is MAXSTREAMS\n"); exit(4); } lflag++; trflag++; if(Uflag) { printf("Can not run throughput tests with unmount & remounts.\n"); exit(5); } break; case 'u': /* Set upper thread/proc limit */ maxt = (long long)(atoi(optarg)); if(maxt <= 0) maxt=1; if(maxt > MAXSTREAMS){ printf("Invalid options: maximum streams for "); printf("throughput is MAXSTREAMS\n"); exit(6); } uflag++; trflag++; if(Uflag) { printf("Can not run throughput tests with unmount & remounts.\n"); exit(7); } break; case 'm': /* Use multiple buffers */ fetchon=0; multi_buffer=1; mflag++; mbuffer = (char *) alloc_mem((long long)MAXBUFFERSIZE,(int)0); if(mbuffer == 0) { perror("Memory allocation failed:"); exit(8); } sprintf(splash[splash_line++],"\tMulti_buffer. Work area %d bytes\n", MAXBUFFERSIZE); break; case 'M': /* Report machine name and OS */ bzero(reply,sizeof(reply)); pi=popen("uname -a", "r"); if(pi == (FILE *)0) { sprintf(splash[splash_line++],"\n\tError using popen() on uname\n"); sprintf(splash[splash_line++],"\t-M option suppressed.\n"); } else { junk=fread(reply,IBUFSIZE-1,1,pi); pclose(pi); m=reply; while(*m) /* Strip new line */ { if(*m=='\n') *m=0; else m++; } sprintf(splash[splash_line++],"\n\tMachine = %s\n",reply); } break; case 'P': /* Set beginning processor for binding. */ #ifndef NO_THREADS #if defined(_HPUX_SOURCE) || defined(linux) #if defined(_HPUX_SOURCE) num_processors= pthread_num_processors_np(); #else num_processors = sysconf(_SC_NPROCESSORS_ONLN); #endif begin_proc = atoi(optarg); if(begin_proc < 0) begin_proc=0; if(begin_proc > num_processors) begin_proc=0; sprintf(splash[splash_line++],"\tBinding of processors beginning with %d \n",begin_proc); ioz_processor_bind++; #else sprintf(splash[splash_line++],"\tProcessor binding not available in this version\n"); #endif #endif break; case 'p': /* purge the processor cache */ sprintf(splash[splash_line++],"\tPurge Mode On\n"); fetchon=0; pflag++; purge=1; break; case 'h': /* show help */ hflag++; show_help(); exit(0); break; case 'E': /* Extended testing for pread/pwrite... */ Eflag++; break; case 'R': /* Generate Excel compatible Report */ Rflag++; sprintf(splash[splash_line++],"\tExcel chart generation enabled\n"); break; case 'o': /* Open OSYNC */ sprintf(splash[splash_line++],"\tSYNC Mode. \n"); oflag++; break; case 'O': /* Report in Ops/sec instead of kB/sec */ sprintf(splash[splash_line++],"\tOPS Mode. Output is in operations per second.\n"); OPS_flag++; break; case 'N': /* Report in usec/op */ sprintf(splash[splash_line++],"\tMicroseconds/op Mode. Output is in microseconds per operation.\n"); MS_flag++; break; case 'V': /* Turn on Verify every byte */ sverify=0; inp_pat = (char)(atoi(optarg)); if(inp_pat == 0) inp_pat = PATTERN; pattern = ((inp_pat << 24) | (inp_pat << 16) | (inp_pat << 8) | inp_pat); verify=1; sprintf(splash[splash_line++],"\tVerify Mode. Pattern %x\n",pattern); sprintf(splash[splash_line++],"\tPerformance measurements are invalid in this mode.\n"); break; case 'S': /* Set the processor cache size */ cache_size = (long)(atoi(optarg)*1024); if(cache_size == 0) cache_size = MY_CACHE_SIZE; break; case 'L': /* Set processor cache line size */ cache_line_size = (long)(atoi(optarg)); if(cache_line_size == 0) cache_line_size = MY_CACHE_LINE_SIZE; break; case 'f': /* Specify the file name */ if(mfflag) { printf("invalid options: -f and -F are mutually exclusive\n"); exit(10); } fflag++; strcpy(filename,optarg); sprintf(dummyfile[0],"%s.DUMMY",optarg); break; case 'b': /* Specify the biff file name */ Rflag++; bif_flag++; strcpy(bif_filename,optarg); break; case 'F': /* Specify multiple file names for -t */ mfflag++; F_flag++; if(fflag) { printf("invalid options: -f and -F are mutually exclusive\n"); exit(11); } if(!trflag) { printf("invalid options: must specify -t N before -F\n"); exit(12); } optind--; for(fileindx=0;fileindx argc) { #ifdef NO_PRINT_LLD printf("invalid options: not enough filenames for %ld streams\n",num_child); #else printf("invalid options: not enough filenames for %lld streams\n",num_child); #endif exit(13); } } break; case 'r': /* Specify the record size to use */ rflag++; reclen = ((long long)(atoll(optarg))*1024LL); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ reclen = (long long)(1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ reclen = (long long)(1024LL * 1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ reclen = (long long)(1024LL * 1024LL * 1024LL *(long long)atoll(optarg)); } if(reclen <= 0) reclen=(long long)4096; r_range[r_count++]=reclen; max_rec_size = (off64_t)r_range[r_count-1]; /* Make visable globally */ min_rec_size = (off64_t)r_range[0]; /* Make visable globally */ #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tRecord Size %ld kB\n",reclen/1024); #else sprintf(splash[splash_line++],"\tRecord Size %lld kB\n",reclen/1024); #endif if(max_rec_size > MAXBUFFERSIZE) { #ifdef NO_PRINT_LLD printf("Error: maximum record size %ld kB is greater than maximum buffer size %ld kB\n ", max_rec_size/1024, MAXBUFFERSIZE/1024); #else printf("Error: maximum record size %lld kB is greater than maximum buffer size %lld kB\n ", (long long)(max_rec_size/1024LL), (long long)MAXBUFFERSIZE/1024LL); #endif exit(23); } break; case 'J': /* Specify the compute time in millisecs */ compute_time = (float)(atoi(optarg)); compute_time=compute_time/1000; if(compute_time < (float)0) compute_time=(float)0; else compute_flag=1; jflag++; break; case 'j': /* Specify the stride in records */ stride = (long long)(atoi(optarg)); if(stride < 0) stride=0; stride_flag=1; break; case 't': /* Specify the number of children to run */ num_child1=(atoi(optarg)); num_child = (long long)num_child1; if(num_child > (long long)MAXSTREAMS) { printf("invalid options: maximum streams for throughput is MAXSTREAMS\n"); #ifdef NO_PRINT_LLD printf("Numchild %ld %s\n",num_child,optarg); #else printf("Numchild %lld %s\n",num_child,optarg); #endif exit(14); } if(num_child <= 0) num_child = 8; if(num_child == 0) num_child=1; t_range[t_count++]=num_child; maxt = (maxt>num_child?maxt:num_child); trflag++; if(Uflag) { printf("Can not run throughput tests with unmount & remounts.\n"); exit(15); } #ifdef NO_THREADS if(burst_size_kb_64 != -1 && burst_sleep_duration_msec != -1) { printf("Can not run throughput tests with burst option.\n"); exit(100); } #endif break; case 'd': /* Specify the delay of children to run */ delay_start = (long long)(atoi(optarg)); if(delay_start < 0) delay_start=0; break; case 'i': /* Specify specific tests */ tval=(long long)(atoi(optarg)); if(tval < 0) tval=0; #ifndef HAVE_PREAD if(tval > RANDOM_MIX_TEST) { printf("\tPread tests not available on this operating system.\n"); exit(183); } #endif if(tval > (long long)(sizeof(func)/sizeof(char *))) { tval=0; sprintf(splash[splash_line++],"\tSelected test not available on the version.\n"); } include_test[tval]++; include_tflag++; break; case 'v': /* Show version information */ for(ind=0; strlen(head1[ind]); ind++) { printf("%s\n", head1[ind]); } exit(0); break; case 'U': /* Specify the dev name for umount/mount*/ Uflag++; strcpy(mountname,optarg); if(trflag) { printf("Can not run throughput tests with unmount & remounts.\n"); exit(16); } break; case 'w': /* Do not unlink files */ sprintf(splash[splash_line++],"\tSetting no_unlink\n"); no_unlink = 1; break; case 'Z': /* Turn on the mmap and file I/O mixing */ sprintf(splash[splash_line++],"\tEnable mmap & file I/O mixing.\n"); mmap_mix = 1; break; case 'W': /* Read/Write with file locked */ file_lock=1; sprintf(splash[splash_line++],"\tLock file when reading/writing.\n"); break; case 'K': /* Cause disrupted read pattern */ disrupt_flag=1; sprintf(splash[splash_line++],"\tDisrupted read patterns selected.\n"); break; case 'X': /* Open write telemetry file */ compute_flag=1; sverify=2; /* touch lightly */ w_traj_flag=1; strcpy(write_traj_filename,optarg); traj_vers(); w_traj_size(); sprintf(splash[splash_line++],"\tUsing write telemetry file \"%s\"\n", write_traj_filename); w_traj_fd=open_w_traj(); if(w_traj_fd == (FILE *)0) exit(200); break; case 'Y': /* Open Read telemetry file */ compute_flag=1; sverify=2; /* touch lightly */ r_traj_flag=1; strcpy(read_traj_filename,optarg); sprintf(splash[splash_line++],"\tUsing read telemetry file \"%s\"\n", read_traj_filename); traj_vers(); r_traj_size(); r_traj_fd=open_r_traj(); if(r_traj_fd == (FILE*) 0) exit(200); break; case 'n': /* Set min file size for auto mode */ nflag=1; minimum_file_size = (off64_t)atoll(optarg); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ ; } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ minimum_file_size = (long long)(1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ minimum_file_size = (long long)(1024LL * 1024LL * (long long)atoll(optarg)); } if(minimum_file_size < RECLEN_START/1024) minimum_file_size=(off64_t)(RECLEN_START/1024); if(minimum_file_size < page_size/1024) minimum_file_size=(off64_t)(page_size/1024); #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tUsing minimum file size of %ld kilobytes.\n",(long long)minimum_file_size); #else sprintf(splash[splash_line++],"\tUsing minimum file size of %lld kilobytes.\n",(long long)minimum_file_size); #endif break; case 'g': /* Set maximum file size for auto mode */ gflag=1; maximum_file_size = (off64_t)atoll(optarg); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ ; } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ maximum_file_size = (long long)(1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ maximum_file_size = (long long)(1024LL * 1024LL * (long long)atoll(optarg)); } if(maximum_file_size < RECLEN_START/1024LL) maximum_file_size=(off64_t)(RECLEN_START/1024LL); #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tUsing maximum file size of %ld kilobytes.\n",(long long)maximum_file_size); #else sprintf(splash[splash_line++],"\tUsing maximum file size of %lld kilobytes.\n",(long long)maximum_file_size); #endif break; case 'z': /* Set no cross over */ sprintf(splash[splash_line++],"\tCross over of record size disabled.\n"); NOCROSSflag=1; break; case 'y': /* Set min record size for auto mode */ yflag=1; min_rec_size = ((long long)(atoll(optarg))*1024); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ min_rec_size = (long long)(1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ min_rec_size = (long long)(1024LL * 1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ min_rec_size = (long long)(1024LL * 1024LL * 1024LL *(long long)atoll(optarg)); } if(min_rec_size <= 0) min_rec_size=(long long)RECLEN_START; #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tUsing Minimum Record Size %ld kB\n", min_rec_size/1024LL); #else sprintf(splash[splash_line++],"\tUsing Minimum Record Size %lld kB\n", min_rec_size/1024LL); #endif break; case 'q': /* Set max record size for auto mode */ qflag=1; max_rec_size = ((long long)(atoll(optarg))*1024); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ max_rec_size = (long long)(1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ max_rec_size = (long long)(1024LL * 1024LL * atoll(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ max_rec_size = (long long)(1024LL * 1024LL * 1024LL *(long long)atoll(optarg)); } if(max_rec_size <= 0) min_rec_size=(long long)RECLEN_END; if(max_rec_size > MAXBUFFERSIZE) { #ifdef NO_PRINT_LLD printf("Error: maximum record size %ld kB is greater than maximum buffer size %ld kB\n ", max_rec_size/1024, MAXBUFFERSIZE/1024); #else printf("Error: maximum record size %lld kB is greater than maximum buffer size %lld kB\n ", (long long)(max_rec_size/1024LL), (long long)MAXBUFFERSIZE/1024LL); #endif exit(23); } #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tUsing Maximum Record Size %ld kB\n", max_rec_size/1024); #else sprintf(splash[splash_line++],"\tUsing Maximum Record Size %lld kB\n", max_rec_size/1024); #endif break; /* * The + operator is for the new extended options mechanism * Syntax is -+ followed by option leter, and if the optino * takes an operand then it is implemented below. An example * -+a arg is shown below. This is a sub option with an argument. * -+b is shown below. This is a sub option with no argument. */ case '+': /* percent to make data compressible */ switch (*((char *)optarg)) { case 'a':/* Max value for random byte [0,255] */ subarg = argv[optind++]; if(subarg==(char *)0) { printf("-+a takes an operand !!\n"); exit(200); } zero_pct = atoi(subarg); if(zero_pct >100) zero_pct = 100; sprintf(splash[splash_line++],"\tZero Percent %d\n ",zero_pct); break; case 'Q': /* Dedup granule size */ subarg = argv[optind++]; if(subarg==(char *)0) { printf("-+Q takes an operand !!\n"); exit(200); } dedup_granule_size = atoi(subarg); if(dedup_granule_size <0) dedup_granule_size = 0; sprintf(splash[splash_line++],"\tDedup granule size %d\n",dedup_granule_size); dedup_unit_step = dedup_granule_size >> 2; break; case 'b': /* burst */ #ifdef NO_THREADS if(trflag) { printf("Can not run throughput tests with burst option.\n"); exit(100); } #endif subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+b takes an operand !!\n"); exit(200); } if (strchr(subarg,',') == NULL) { printf("-+b operand is of the format #,# (burst size (K/M/G) ,mili-second) !!\n"); exit(400); } burst_sleep_duration_msec = atoi(strchr(subarg,',') + 1); if (burst_sleep_duration_msec == 0) { printf("-+b cannot parse sleep duration !!\n"); exit(400); } *strchr(subarg,',') = '\0'; #ifdef NO_PRINT_LLD sscanf(subarg,"%ld",(long long *)&burst_size_kb_64); #else sscanf(subarg,"%lld",(long long *)&burst_size_kb_64); #endif if(subarg[strlen(subarg)-1]=='k' || subarg[strlen(subarg)-1]=='K'){ ; } if(subarg[strlen(subarg)-1]=='m' || subarg[strlen(subarg)-1]=='M'){ burst_size_kb_64 = burst_size_kb_64 * 1024; } if(subarg[strlen(optarg)-1]=='g' || subarg[strlen(optarg)-1]=='G'){ burst_size_kb_64 = burst_size_kb_64 * 1024 * 1024; } if (burst_size_kb_64 <= 0) { printf("-+b cannot parse burst size '%s'!!\n",subarg); exit(400); } *(subarg + strlen(subarg)) = ','; /* so it will be printed when dumping the argsuments */ break; case 'F': /* Example: Does not have an argument */ del_flag = 1; break; case 'M': /* Speical dedup+compress option. Experimental */ N_special = 1; sprintf(splash[splash_line++],"\tDedup+compress enabled\n "); break; case 'R': /* Speical Windows option to read filelist from a input file. Experimental */ mfflag++; subarg = argv[optind++]; if(subarg==(char *)0) { printf("-+R takes an operand !!\n"); exit(200); } sprintf(splash[splash_line++],"\tFilenames from a file option enabled. File: %s\n ",subarg); /* filename should be used instead of filelist */ struct stat outbuf; int result; result = stat(subarg, &outbuf); if(result == -1) { printf("Failed to stat the iozone input file: %s\n",argv[optind]); exit(errno); } else { /* read the input file and populate the filearray */ int fileindx = 0; FILE * fp; char * lbuffer; fp = fopen(subarg, "r"); while ( 1 ) { lbuffer=malloc(MAXNAMESIZE); memset(lbuffer,0,MAXNAMESIZE); if(fgets(lbuffer,MAXNAMESIZE,fp) == 0) break; if(strlen(lbuffer) > 0) { /* strip newline */ if(lbuffer[strlen(lbuffer)-1] == '\n') lbuffer[strlen(lbuffer)-1] = 0; filearray[fileindx]= lbuffer; fileindx++; } } fclose(fp); if(fileindx > num_child) { #ifdef NO_PRINT_LLD printf("invalid options: not enough filenames for %ld streams\n",num_child); #else printf("invalid options: not enough filenames for %lld streams\n",num_child); #endif exit(13); } } break; case 'c': /* Argument is the controlling host name */ /* I am a client for distributed Iozone */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+c takes an operand !!\n"); exit(200); } strcpy(controlling_host_name,subarg); distributed=1; client_iozone=1; master_iozone=0; break; case 'h': /* Argument is the controlling host name */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+h takes an operand !!\n"); exit(200); } strcpy(controlling_host_name,subarg); sprintf(splash[splash_line++],"\tHostname = %s\n",controlling_host_name); break; case 'm': /* I am the controlling process for distributed Iozone */ /* Does not have an argument */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+m takes an operand. ( filename )\n"); exit(201); } strcpy(client_filename,subarg); ret=get_client_info(); if(ret <= 0) { printf("Error reading client file\n"); exit(178); } clients_found=ret; distributed=1; master_iozone=1; client_iozone=0; sprintf(splash[splash_line++],"\tNetwork distribution mode enabled.\n"); break; case 'N': /* turn off truncating the file before write test */ notruncate = 1; break; case 'u': /* Set CPU utilization output flag */ cpuutilflag = 1; /* only used if R(eport) flag is also set */ get_rusage_resolution(); sprintf(splash[splash_line++],"\tCPU utilization Resolution = %5.3f seconds.\n",cputime_res); sprintf(splash[splash_line++],"\tCPU utilization Excel chart enabled\n"); break; case 's': /* Clients operate in silent mode. */ /* Does not have an argument */ silent=1; break; case 'd': /* Diagnostics mode */ sprintf(splash[splash_line++],"\t>>> I/O Diagnostic mode enabled. <<<\n"); sprintf(splash[splash_line++],"\tPerformance measurements are invalid in this mode.\n"); diag_v=1; sverify=0; break; case 'x': /* Argument is the multiplier for rec size and file size */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+c takes an operand !!\n"); exit(200); } multiplier = atoi(subarg); if(multiplier <=1) multiplier = 2; break; case 'i': /* Argument is the host port */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+i takes an operand !!\n"); exit(200); } controlling_host_port = atoi(subarg); break; case 'p': /* Argument is the percentage read */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+p takes an operand !!\n"); exit(200); } pct_read = atoi(subarg); if(pct_read < 1) pct_read = 1; if(pct_read >=100) pct_read = 100; sprintf(splash[splash_line++],"\tPercent read in mix test is %d\n",pct_read); break; case 't': /* Speed code activated */ speed_code=1; break; #if defined(_HPUX_SOURCE) || defined(linux) || defined(solaris) case 'r': /* Read sync too */ read_sync=1; sprintf(splash[splash_line++],"\tRead & Write sync mode active.\n"); break; #endif #ifndef NO_MADVISE case 'A': /* Argument is madvise selector */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+A take an operand !!\n"); exit(200); } advise_flag=1; advise_op=atoi(subarg); sprintf(splash[splash_line++],"\tMadvise enabled: %d\n",advise_op); break; #endif case 'n': /* Set no-retest */ noretest = 1; sprintf(splash[splash_line++],"\tNo retest option selected\n"); break; case 'k': /* Constant aggregate data set size */ aggflag=1; break; case 'q': /* Argument is the rest time between tests in seconds */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+q takes an operand !!\n"); exit(200); } rest_val = (long long)atoi(subarg); if(rest_val <=0) rest_val = 0; restf=1; sprintf(splash[splash_line++],"\tDelay %d seconds between tests enabled.\n",atoi(subarg)); break; #if defined(O_DSYNC) case 'D': /* O_DSYNC mode */ sprintf(splash[splash_line++],"\t>>> O_DSYNC mode enabled. <<<\n"); odsync=1; break; #endif case 'l': /* Record locking mode */ sprintf(splash[splash_line++],"\t>>> Record locking mode enabled. <<<\n"); rlocking=1; break; case 'L': /* Record locking mode shared files*/ sprintf(splash[splash_line++],"\t>>> Record locking, shared file mode enabled. <<<\n"); share_file=1; rlocking=1; break; case 'J': /* Thinktime is included in thrhoughput */ sprintf(splash[splash_line++],"\t>>> Think time is included in throughput cal. <<<\n"); inc_think=1; break; case 'V': /* No Record locking shared files*/ sprintf(splash[splash_line++],"\t>>> Shared file mode enabled. <<<\n"); share_file=1; break; case 'B': /* Sequential mix */ sprintf(splash[splash_line++],"\t>>> Sequential Mixed workload. <<<\n"); seq_mix=1; break; /* Use an existing user file, that does not contain Iozone's pattern. Use file for testing, but read only, and no delete at the end of the test. Also, no pattern verification, but do touch the pages. */ case 'E': sprintf(splash[splash_line++],"\t>>> No Verify mode. <<<\n"); sverify=2; no_unlink=1; no_write=1; break; case 'T': /* Time stamps on */ L_flag=1; break; case 'X': /* Short circuit test mode */ X_flag = 1; sverify=1; verify=1; inp_pat = 0xBB; pattern = ((inp_pat << 24) | (inp_pat << 16) | (inp_pat << 8) | inp_pat); sprintf(splash[splash_line++],"\tShort circuit mode. For\n"); sprintf(splash[splash_line++],"\t filesystem development testing ONLY !\n"); break; case 'Z': /* Compatibility mode for 0xA5 */ Z_flag = 1; sverify=1; verify=1; inp_pat = 0xA5; pattern = ((inp_pat << 24) | (inp_pat << 16) | (inp_pat << 8) | inp_pat); sprintf(splash[splash_line++],"\tUsing old data sets.\n"); sprintf(splash[splash_line++],"\t Performance measurements may be invalid in this\n"); sprintf(splash[splash_line++],"\t mode due to published hack.\n"); break; #if defined(Windows) case 'U': /* Windows only Unbufferd I/O */ unbuffered=1; sprintf(splash[splash_line++],"\tUnbuffered Windows API usage. >>> Very Experimental <<<\n"); break; #endif case 'K': /* Sony special for manual control of test 8 */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+K takes an operand !!\n"); exit(204); } Kplus_readers = (int)atoi(subarg); if(Kplus_readers <=0) Kplus_readers = 1; Kplus_flag=1; sprintf(splash[splash_line++],"\tManual control of test 8. >>> Very Experimental. Sony special <<<\n"); break; case 'w': /* Argument is the percent of dedup */ /* Sets size of dedup region across files */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+w takes an operand !!\n"); exit(200); } dedup = atoi(subarg); if(dedup <=0) dedup = 0; if(dedup >100) dedup = 100; dedup_flag = 1; sprintf(splash[splash_line++],"\tDedup activated %d percent.\n",dedup); break; case 'y': /* Argument is the percent of interior dedup */ /* Sets size of dedup region within and across files */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+y takes an operand !!\n"); exit(200); } dedup_interior = atoi(subarg); if(dedup_interior <0) dedup_interior = 0; if(dedup_interior >100) dedup_interior = 100; dedup_iflag = 1; sprintf(splash[splash_line++],"\tDedup within & across %d percent.\n",dedup_interior); break; case 'C': /* Argument is the percent of dedup within & !across */ /* Sets size of dedup region within and !across files */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+C takes an operand !!\n"); exit(200); } dedup_compress = atoi(subarg); if(dedup_compress <0) dedup_compress = 0; if(dedup_compress >100) dedup_compress = 100; dedup_bflag = 1; sprintf(splash[splash_line++],"\tDedup within %d percent.\n",dedup_compress); break; case 'S': /* Argument is the seed for dedup */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+S takes an operand !!\n"); exit(200); } dedup_mseed = atoi(subarg); if(dedup_mseed ==0) dedup_mseed = 1; sprintf(splash[splash_line++],"\tDedup manual seed %d .\n",dedup_mseed); break; case 'W': /* Argument is the child_skew for dedup */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+W takes an operand !!\n"); exit(200); } chid_skew = atoi(subarg); sprintf(splash[splash_line++],"\tDedup chid_skew %d .\n",chid_skew); break; case 'H': /* Argument is hostname of the PIT */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+H takes operand !!\n"); exit(200); } strcpy(pit_hostname,subarg); sprintf(splash[splash_line++],"\tPIT_host %s\n",pit_hostname); break; case 'P': /* Argument is port of the PIT */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+P takes operand !!\n"); exit(200); } strcpy(pit_service,subarg); sprintf(splash[splash_line++],"\tPIT_port %s\n",pit_service); break; case 'z': /* Enable hist summary*/ hist_summary=1; sprintf(splash[splash_line++],"\tHistogram summary enabled.\n"); break; case 'O': /* Argument is the Op rate */ subarg=argv[optind++]; if(subarg==(char *)0) { printf("-+O takes an operand !!\n"); exit(200); } op_rate = atoi(subarg); if(op_rate <= 0) op_rate = 1; op_rate_flag = 1; sprintf(splash[splash_line++],"\tRate control active %d Ops/sec .\n",op_rate); break; default: printf("Unsupported Plus option -> %s <-\n",optarg); exit(255); break; } break; default: printf("Unsupported option -> %s <-\n",optarg); exit(255); } } touch_dedup(buffer1, MAXBUFFERSIZE); base_time=(long)time_so_far(); get_resolution(); /* Get clock resolution */ if(speed_code) { do_speed_check(client_iozone); exit(0); } if(r_count > 1) { aflag=1; rflag=0; NOCROSSflag=1; } if(s_count > 1) { aflag=1; sflag=0; NOCROSSflag=1; } /* * If not in silent mode then display the splash screen. */ for(i=0;i clients_found) { printf("You can not specify more threads/processes than you have in the client file list\n"); exit(202); } } if(!OPS_flag && !MS_flag) { if(!silent) printf("\tOutput is in kBytes/sec\n"); } if (min_rec_size > max_rec_size) { #ifdef NO_PRINT_LLD printf("Error: minimum record size %ld kB is greater than maximum record size %ld kB\n ", min_rec_size/1024, max_rec_size/1024); #else printf("Error: minimum record size %lld kB is greater than maximum record size %lld kB\n ", min_rec_size/1024, max_rec_size/1024); #endif exit(23); } orig_min_rec_size=min_rec_size; orig_max_rec_size=max_rec_size; /* * No telemetry files... just option selected */ if(compute_flag && jflag && !(r_traj_flag || w_traj_flag)) if(!silent) printf("\tCompute time %f seconds for reads and writes.\n",compute_time); /* * Read telemetry file and option selected */ if(compute_flag && r_traj_flag && !w_traj_flag) { if(r_traj_items==3) { if(!silent) printf("\tCompute time from telemetry files for reads.\n"); } else { if(jflag) if(!silent) printf("\tCompute time %f seconds for reads.\n",compute_time); } if(jflag) if(!silent) printf("\tCompute time %f seconds for writes.\n",compute_time); } /* * Write telemetry file and option selected */ if(compute_flag && !r_traj_flag && w_traj_flag) { if(w_traj_items==3) { if(!silent) printf("\tCompute time from telemetry files for writes.\n"); } else { if(jflag) if(!silent) printf("\tCompute time %f seconds for writes.\n",compute_time); } if(jflag) if(!silent) printf("\tCompute time %f seconds for reads.\n",compute_time); } if(compute_flag && r_traj_flag && w_traj_flag && jflag) { if(r_traj_items==3) { if(!silent) printf("\tCompute time from telemetry files for reads.\n"); } else { if(!silent) printf("\tCompute time %f seconds for reads.\n",compute_time); } if(w_traj_items==3) { if(!silent) printf("\tCompute time from telemetry files for writes.\n"); } else { if(!silent) printf("\tCompute time %f seconds for writes.\n",compute_time); } } if(compute_flag && r_traj_flag && w_traj_flag && !jflag) { if(r_traj_items==3) { if(!silent) printf("\tCompute time from telemetry files for reads.\n"); } else { if(!silent) printf("\tNo compute time for reads.\n"); } if(w_traj_items==3) { if(!silent) printf("\tCompute time from telemetry files for writes.\n"); } else { if(!silent) printf("\tNo compute time for writes.\n"); } } /* Enforce only write,rewrite,read,reread */ if(w_traj_flag || r_traj_flag) { for(i=2;i<(long long)(sizeof(func)/sizeof(char *));i++) { if(seq_mix && (i==8)) ; else include_test[i] = 0; } } if(r_traj_flag) { if(include_test[READER_TEST] == 0) { include_test[WRITER_TEST]=1; include_test[READER_TEST]=1; include_tflag=1; } } if(w_traj_flag) { if(include_test[WRITER_TEST] == 0) { include_test[WRITER_TEST]=1; include_tflag=1; } } if(w_traj_flag && w_traj_fsize != 0) kilobytes64=w_traj_fsize/1024; if(r_traj_flag && r_traj_fsize != 0) kilobytes64=r_traj_fsize/1024; if( sverify==0 && (w_traj_flag || r_traj_flag)) { printf("\n\tFull verification not supported in telemetry mode.\n\n"); exit(17); } ; if(disrupt_flag &&(w_traj_flag || r_traj_flag) ) { printf("\n\tDisrupt not supported in telemetry mode.\n\n"); exit(17); } if(aflag &&(w_traj_flag || r_traj_flag) ) { printf("\n\tAuto mode not supported in telemetry mode.\n"); printf("\tTry: -i 0 -i 1 \n\n"); exit(17); } if(sflag && w_traj_flag ) { printf("\n\tSize of file is determined by telemetry file.\n\n"); exit(17); } if(rflag && w_traj_flag ) { printf("\n\tRecord size of file is determined by telemetry file.\n\n"); exit(17); } if(stride_flag && (w_traj_flag || r_traj_flag)) { printf("\n\tStride size is determined by telemetry file.\n\n"); exit(17); } if(trflag && MS_flag) { printf("\n\tMicrosecond mode not supported in throughput mode.\n\n"); exit(17); } if (trflag /* throughput mode, don't allow auto-mode options: */ && (auto_mode || aflag || yflag || qflag || nflag || gflag)) { printf("\n\tCan not mix throughput mode and auto-mode flags.\n\n"); exit(17); } if(fflag && trflag) { printf("\n\tYou must use -F when using multiple threads or processes.\n\n"); exit(17); } if(aflag && mfflag) { printf("\n\tYou must use -f when using auto mode.\n\n"); exit(17); } if(async_flag && mmapflag) { printf("\n\tSorry ... Only mmap or async but not both\n\n"); exit(18); } #ifndef ASYNC_IO if(async_flag) { printf("\n\tSorry ... This version does not support async I/O\n\n"); exit(19); } #endif if(no_write) { if(!include_tflag) { printf("You must specify which tests ( -i # ) when using -+E\n"); exit(19); } } if(include_tflag) { for(i=0;i<(long long)(sizeof(func)/sizeof(char *));i++) if(include_test[i]) include_mask|=(long long)(1<> %llx",include_mask); HERE */ } if(no_write) /* Disable if any writer would disturbe existing file */ { if(include_test[0] || include_test[4] || include_test[6] || include_test[8] || include_test[9] || include_test[11]) { printf("You must disable any test that writes when using -+E\n"); exit(20); } } if(no_write) /* User must specify the existing file name */ { if(!(fflag | mfflag)) { printf("You must use -f or -F when using -+E\n"); exit(20); } } if(h_flag && k_flag) { printf("\n\tCan not do both -H and -k\n"); exit(20); } if((dedup_flag | dedup_iflag) && diag_v) { printf("\n\tCan not do both -+d and -+w\n"); exit(20); } if(!aflag && !rflag) max_rec_size=min_rec_size; init_record_sizes(min_rec_size,max_rec_size); if(!silent) printf("\tTime Resolution = %1.6f seconds.\n",time_res); #ifdef NO_PRINT_LLD if(!silent) printf("\tProcessor cache size set to %ld kBytes.\n",cache_size/1024); if(!silent) printf("\tProcessor cache line size set to %ld bytes.\n",cache_line_size); if(!silent) printf("\tFile stride size set to %ld * record size.\n",stride); #else if(!silent) printf("\tProcessor cache size set to %ld kBytes.\n",cache_size/1024); if(!silent) printf("\tProcessor cache line size set to %ld bytes.\n",cache_line_size); if(!silent) printf("\tFile stride size set to %lld * record size.\n",stride); #endif if (burst_size_kb_64 != -1 && !silent) #ifdef NO_PRINT_LLD printf("\tBurst size set to %ld Kbytes.\n\tBurst sleep duration set to %ld msec\n", (long long)burst_size_kb_64, (long long)burst_sleep_duration_msec); #else printf("\tBurst size set to %lld Kbytes.\n\tBurst sleep duration set to %lld msec\n", (long long)burst_size_kb_64, (long long)burst_sleep_duration_msec); #endif if(!rflag) reclen=(long long)4096; if(uflag && !lflag) num_child=mint = 1; if(lflag && !uflag) maxt = mint; if(use_thread) port="thread"; else port="process"; if(lflag || uflag){ #ifdef NO_PRINT_LLD if(!silent) printf("\tMin %s = %ld \n",port,mint); if(!silent) printf("\tMax %s = %ld \n",port,maxt); #else if(!silent) printf("\tMin %s = %lld \n",port,mint); if(!silent) printf("\tMax %s = %lld \n",port,maxt); #endif } if(trflag) { if(num_child > 1) { if(use_thread) { port="threads"; } else { port="processes"; } } #ifdef NO_PRINT_LLD if(!silent) printf("\tThroughput test with %ld %s\n", num_child,port); #else if(!silent) printf("\tThroughput test with %lld %s\n", num_child,port); #endif } numrecs64 = (long long)(kilobytes64*1024)/reclen; if (reclen > (long long)MAXBUFFERSIZE) { #ifdef NO_PRINT_LLD printf("Error: Maximum record length is %ld bytes\n", MAXBUFFERSIZE); #else printf("Error: Maximum record length is %lld bytes\n", (long long)MAXBUFFERSIZE); #endif exit(21); } if (reclen < (long long)MINBUFFERSIZE) { #ifdef NO_PRINT_LLD printf("Error: Minimum record length is %ld bytes\n", MINBUFFERSIZE); #else printf("Error: Minimum record length is %lld bytes\n", (long long)MINBUFFERSIZE); #endif exit(22); } /* Only bzero or fill that which you will use. The buffer is very large */ if(verify ) { fill_buffer((char *)buffer,l_min(reclen,(long long)cache_size),(long long)pattern,(char)sverify,(long long)0); if(pflag) fill_buffer((char *)pbuffer,l_min(reclen,(long long)cache_size),(long long)pattern,(char)sverify,(long long)0); if(mflag) fill_buffer((char *)mbuffer,l_min(reclen,(long long)cache_size),(long long)pattern,(char)sverify,(long long)0); } else { bzero(buffer,(size_t)l_min(reclen,(long long)cache_size)); } #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=begin_proc; #if defined( _HPUX_SOURCE ) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif orig_size=kilobytes64; if(trflag){ (void)multi_throughput_test(mint,maxt); goto out; } if(trflag && (mint == maxt)){ auto_mode=0; throughput_test(); goto out; } if (aflag) { print_header(); auto_test(); goto out; } print_header(); (void) begin(kilobytes64,reclen); out: if(r_traj_flag) fclose(r_traj_fd); if(w_traj_flag) fclose(w_traj_fd); if (!no_unlink) { if(check_filename(dummyfile[0])) unlink(dummyfile[0]); /* delete the file */ } if(!silent) printf("\niozone test complete.\n"); if(res_prob) { printf("Timer resolution is poor. Some small transfers may have \n"); printf("reported inaccurate results. Sizes %ld kBytes and below.\n", (long)(rec_prob/(long long)1024)); } if(Rflag && !trflag){ dump_excel(); } return(0); } #ifdef HAVE_ANSIC_C void record_command_line(int argc, char **argv) #else void record_command_line(argc, argv) int argc; char **argv; #endif { int ix, len = 0; /* print and save the entire command line */ if(!silent) printf("\tCommand line used:"); for (ix=0; ix < argc; ix++) { if(!silent) printf(" %s", argv[ix]); if ((len + strlen(argv[ix])) < sizeof(command_line)) { strcat (command_line, argv[ix]); strcat (command_line, " "); len += strlen(argv[ix]) + 1; } else { printf ("Command line too long to save completely.\n"); break; } } if(!silent) printf("\n"); } /*************************************************************************/ /* BEGIN() */ /* This is the main work horse. It is called from main and from */ /* auto_test. The caller provides the size of file and the record length.*/ /*************************************************************************/ #ifdef HAVE_ANSIC_C void begin(off64_t kilos64,long long reclength) #else void begin(kilos64,reclength) off64_t kilos64; long long reclength; #endif { long long num_tests,test_num,i,j; long long data1[MAXTESTS], data2[MAXTESTS]; num_tests = sizeof(func)/sizeof(char *); #if defined(HAVE_PREAD) if(!Eflag) { #if defined(HAVE_PREAD) && defined(HAVE_PREADV) num_tests -= 4; #else num_tests -= 2; #endif if(mmapflag || async_flag) { num_tests -= 2; } } else { if(mmapflag || async_flag) #if defined(HAVE_PREAD) && defined(HAVE_PREADV) num_tests -= 6; #else num_tests -= 4; #endif } #else if(mmapflag || async_flag) { num_tests -= 2; } #endif if(RWONLYflag) num_tests = 2; /* kcollins 8-21-96*/ sync(); /* just in case there were some dirty */ sync(); kilobytes64=kilos64; reclen=reclength; numrecs64 = (kilobytes64*1024)/reclen; store_value(kilobytes64); if(r_traj_flag || w_traj_flag) store_value((off64_t)0); else store_value((off64_t)(reclen/1024)); #ifdef NO_PRINT_LLD if(!silent) printf("%16ld",kilobytes64); if(r_traj_flag || w_traj_flag) { if(!silent) printf("%8ld",0); } else { if(!silent) printf("%8ld",reclen/1024); } #else if(!silent) printf("%16lld",(long long)kilobytes64); if(r_traj_flag || w_traj_flag) { if(!silent) printf("%8lld",(long long )0); } else { if(!silent) printf("%8lld",(long long)(reclen/1024)); } #endif if(include_tflag) { for(i=0;i (long long)(min_file_size*1024)) { #ifdef NO_PRINT_LLD printf("Error: record length %ld is greater than filesize %ld kB\n ", (long long)min_rec_size,(long long)min_file_size); #else printf("Error: record length %lld is greater than filesize %lld kB\n ", (long long)min_rec_size,(long long)min_file_size); #endif exit(23); } if(NOCROSSflag) xover = max_file_size; init_file_sizes(min_file_size, max_file_size); del_record_sizes(); orig_min_rec_size=min_rec_size; orig_max_rec_size=max_rec_size; init_record_sizes(min_rec_size, max_rec_size); for(kilosi=get_next_file_size((off64_t)0); kilosi>0; kilosi=get_next_file_size(kilosi)) { /****************************************************************/ /* Start with record size of min_rec_size bytes and repeat the */ /* test, multiplying the record size by MULTIPLIER each time, */ /* until we reach max_rec_size. At the CROSSOVER we stop doing */ /* small buffers as it takes forever and becomes very */ /* un-interesting. */ /****************************************************************/ if(!rflag && !sflag && !yflag && !qflag) if(kilosi > xover){ min_rec_size = LARGE_REC; mult = orig_min_rec_size/1024; del_record_sizes(); init_record_sizes(min_rec_size, max_rec_size); /************************************/ /* Generate dummy entries in the */ /* Excel buffer for skipped */ /* record sizes */ /************************************/ for(count1=min_rec_size; (count1 != orig_min_rec_size) && ( mult <= (kilosi*1024)) ; count1=(count1>>1)) { current_x=0; store_value((off64_t)kilosi); store_value((off64_t)mult); for(xx=0;xx<20;xx++) store_value((off64_t)0); mult=mult*2; current_y++; if(current_y>max_y) max_y=current_y; current_x=0; } } for (recszi=get_next_record_size((off64_t)0);recszi!=0;recszi=get_next_record_size(recszi)) { if(recszi > (kilosi*1024)) break; begin(kilosi, recszi ); current_x=0; current_y++; } } } /****************************************************************/ /* */ /* THROUGHPUT_TEST () Multi process throughput test */ /* */ /* Note: States for share memory barrier are: */ /* 0 = Child not running or has finished. */ /* 1 = Child is ready to begin. */ /* 2 = Child is told to begin. */ /****************************************************************/ /* Data in shared memory format is: */ /* */ /* struct child_stats { */ /* long long flag; Used to barrier */ /* double walltime; Child's elapsed time */ /* double cputime; Child's CPU time */ /* double throughput; Child's throughput */ /* double actual; Child's actual read/written */ /* } */ /* */ /* There is an array of child_stat structures layed out in */ /* shared memory. */ /* */ /****************************************************************/ #ifdef HAVE_ANSIC_C void throughput_test(void) #else void throughput_test() #endif { char *unit; double starttime1 = 0; double jstarttime = 0; double jtime = 0; double walltime = 0; double cputime = 0; char *port; char getout; long long throughsize = KILOBYTES; long long xx,xy,i; long long xyz; double ptotal; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; VOLATILE char *temp; double min_throughput = 0; double max_throughput = 0; double avg_throughput = 0; double min_xfer = 0; toutputindex=0; strcpy(&toutput[0][0],throughput_tests[0]); ptotal=written_so_far=read_so_far=re_written_so_far=re_read_so_far=0 ; if(OPS_flag) unit="ops"; else unit="kB"; #ifndef NO_THREADS /*Init barriers*/ if(use_thread) { barrier = (pthread_barrier_t*)alloc_mem(sizeof(pthread_barrier_t), 0); // Not shared pthread_barrierattr_setpshared(&barrier_attr, PTHREAD_PROCESS_PRIVATE); pthread_barrier_init(barrier, &barrier_attr, num_child); } else { barrier = (pthread_barrier_t*)alloc_mem(sizeof(pthread_barrier_t), 1); // Shared pthread_barrierattr_setpshared(&barrier_attr, PTHREAD_PROCESS_SHARED); pthread_barrier_init(barrier, &barrier_attr, num_child); } if (burst_size_kb_64 != -1) burst_size_per_child = burst_size_kb_64 * 1024 / num_child; #endif if(!haveshm) { shmaddr=(struct child_stats *)alloc_mem((long long)SHMSIZE,(int)1); #ifdef _64BIT_ARCH_ if((long long)shmaddr==(long long)-1) #else if((long )shmaddr==(long)-1) #endif { printf("\nShared memory not working\n"); exit(24); } haveshm=(char*)shmaddr; } else shmaddr=(struct child_stats *)haveshm; if(use_thread) stop_flag = &stoptime; else { temp = (char *)&shmaddr[0]; stop_flag = (char *)&temp[(long long)SHMSIZE]-4; } for(xyz=0;xyzflag=CHILD_STATE_HOLD; child_stat->actual=0; child_stat->throughput=0; child_stat->cputime=0; child_stat->walltime=0; } *stop_flag = 0; if(!sflag) kilobytes64=throughsize; if(!rflag) reclen=(long long)4096; if(aggflag) kilobytes64=orig_size/num_child; numrecs64 = (long long)(kilobytes64*1024)/reclen; buffer=mainbuffer; if(use_thread) port="thread"; else port="process"; if(w_traj_flag) { #ifdef NO_PRINT_LLD if(!silent) printf("\tEach %s writes a %ld kByte file in telemetry controlled records\n", port,(long long)kilobytes64); #else if(!silent) printf("\tEach %s writes a %lld kByte file in telemetry controlled records\n", port,(long long)kilobytes64); #endif } else { #ifdef NO_PRINT_LLD if(!silent) printf("\tEach %s writes a %ld kByte file in %ld kbyte records\n", port,(long long)kilobytes64,(long long)reclen/1024); #else if(!silent) printf("\tEach %s writes a %lld kByte file in %lld kByte records\n", port,(long long)kilobytes64,(long long)reclen/1024); #endif } if(fflag) /* Each child has a file name to write */ for(xx=0;xxflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag=CHILD_STATE_BEGIN; if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); /* Start parents timer */ goto waitout; } waitout: getout=0; if((long long)getpid() == myid) { /* Parent only */ starttime1 = time_so_far(); /* Wait for all children */ for( i = 0; i < num_child; i++){ child_stat = (struct child_stats *) &shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* get parents total time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; walltime = 0.0; cputime = 0.0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; /* add up the children */ ptotal += child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; /* Add up the cpu times of all children */ cputime += child_stat->cputime; /* and find the child with the longest wall time */ /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } for(xyz=0;xyzflag = CHILD_STATE_HOLD; /* Start children at state 0 (HOLD) */ } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %2ld initial writers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2ld initial writers \t= %10.2f %s/sec\n",num_child,((double)(ptotal)/total_time),unit); #else if(!silent) printf("\tChildren see throughput for %2lld initial writers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2lld initial writers \t= %10.2f %s/sec\n",num_child,((double)(ptotal)/total_time),unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU Utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Write"); /**********************************************************/ /*************** End of intitial writer *******************/ /**********************************************************/ sync(); sleep(2); if(restf) sleep((int)rest_val); *stop_flag=0; if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } /**********************************************************/ /* Re-write throughput performance test. ******************/ /**********************************************************/ walltime = 0.0; cputime = 0.0; jstarttime=0; total_kilos=0; toutputindex=1; strcpy(&toutput[1][0],throughput_tests[1]); if(noretest) { store_dvalue( (double)0); goto next0; } if((!distributed) || (distributed && master_iozone)) start_monitor("Rewrite"); /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_REWRITE_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(28); } if(childids[xx] == 0){ #ifdef _64BIT_ARCH_ thread_rwrite_test((int)xx); #else thread_rwrite_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( (void *)thread_rwrite_test,(int)xx); #else childids[xx] = mythread_create( (void *)thread_rwrite_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)myid,(long long)SIGTERM); } exit(29); } } } #endif if((long long)myid == getpid()) { if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); goto jump3; } jump3: getout=0; if((long long)myid == getpid()){ /* Parent only here */ for( i = 0; i < num_child; i++){ child_stat=(struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents total time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { /* if (walltime < cputime_res) walltime = 0.0; */ if (cputime < cputime_res) cputime = 0.0; } for(xyz=0;xyzflag = CHILD_STATE_HOLD; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %2ld rewriters \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2ld rewriters \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %2lld rewriters \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2lld rewriters \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } *stop_flag=0; if((!distributed) || (distributed && master_iozone)) stop_monitor("Rewrite"); /**********************************************************/ /*************** End of rewrite throughput ****************/ /**********************************************************/ sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next0: if(include_tflag) if(!(include_mask & (long long)READER_MASK)) goto next1; /**************************************************************/ /*** Reader throughput tests **********************************/ /**************************************************************/ if((!distributed) || (distributed && master_iozone)) start_monitor("Read"); toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[2]); walltime = 0.0; cputime = 0.0; jstarttime=0; total_kilos=0; if(distributed) { use_thread=0; if(master_iozone) master_listen_socket=start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_READ_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(30); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_read_test((int)xx); #else thread_read_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_read_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_read_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(31); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); goto jumpend4; } jumpend4: getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %2ld readers \t\t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2ld readers \t\t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %2lld readers \t\t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2lld readers \t\t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Read"); /**********************************************************/ /*************** End of readers throughput ****************/ /**********************************************************/ sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } /**************************************************************/ /*** ReReader throughput tests **********************************/ /**************************************************************/ toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[3]); if(noretest) { store_dvalue( (double)0); goto next1; } if((!distributed) || (distributed && master_iozone)) start_monitor("Reread"); walltime = 0.0; cputime = 0.0; jstarttime=0; *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_REREAD_TEST, numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(32); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_rread_test((int)xx); #else thread_rread_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_rread_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_rread_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(33); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); goto jumpend2; } jumpend2: getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif min_throughput=max_throughput=min_xfer=0; total_kilos=0; ptotal=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { /* if (walltime < cputime_res) walltime = 0.0; */ if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld re-readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld re-readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld re-readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld re-readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Reread"); /**********************************************************/ /*************** End of re-readers throughput ****************/ /**********************************************************/ sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next1: if(include_tflag) if(!(include_mask & (long long)REVERSE_MASK)) goto next2; sync(); sleep(2); /**************************************************************/ /*** Reverse reader throughput tests **************************/ /**************************************************************/ toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[4]); if((!distributed) || (distributed && master_iozone)) start_monitor("Revread"); walltime = 0.0; cputime = 0.0; jstarttime=0; *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_REVERSE_READ_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(34); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_reverse_read_test((int)xx); #else thread_reverse_read_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_reverse_read_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_reverse_read_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(35); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; /* walltime += child_stat->walltime; */ cputime += child_stat->cputime; /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { /* if (walltime < cputime_res) walltime = 0.0; */ if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld reverse readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld reverse readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld reverse readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld reverse readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Revread"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next2: if(include_tflag) if(!(include_mask & (long long)STRIDE_READ_MASK)) goto next3; /**************************************************************/ /*** stride reader throughput tests **************************/ /**************************************************************/ toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[5]); if((!distributed) || (distributed && master_iozone)) start_monitor("Strideread"); walltime = 0.0; cputime = 0.0; jstarttime=0; sync(); sleep(2); *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_STRIDE_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(36); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_stride_read_test((int)xx); #else thread_stride_read_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_stride_read_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_stride_read_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(37); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; /* walltime += child_stat->walltime; */ cputime += child_stat->cputime; /* Get the biggest walltime */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { /* if (walltime < cputime_res) walltime = 0.0; */ if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld stride readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld stride readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld stride readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld stride readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Strideread"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } /**************************************************************/ /*** random reader throughput tests ***************************/ /**************************************************************/ next3: if(include_tflag) if(!(include_mask & (long long)RANDOM_RW_MASK)) goto next4; toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[6]); if((!distributed) || (distributed && master_iozone)) start_monitor("Randread"); walltime = 0.0; cputime = 0.0; jstarttime=0; sync(); sleep(2); *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_RANDOM_READ_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(38); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_ranread_test((int)xx); #else thread_ranread_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_ranread_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_ranread_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(39); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the biggest walltime */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld random readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld random readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld random readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld random readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Randread"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } /**************************************************************/ /*** mixed workload throughput tests ***************************/ /**************************************************************/ next4: if(include_tflag) if(!(include_mask & (long long)RANDOM_MIX_MASK)) goto next5; toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[7]); if((!distributed) || (distributed && master_iozone)) start_monitor("Mixed"); walltime = 0.0; cputime = 0.0; jstarttime=0; sync(); sleep(2); *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_RANDOM_MIX_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(38); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_mix_test((int)xx); #else thread_mix_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_mix_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_mix_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(39); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the biggest walltime */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld mixed workload \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld mixed workload \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld mixed workload \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld mixed workload \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Mixed"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next5: /**************************************************************/ /*** random writer throughput tests **************************/ /**************************************************************/ if(include_tflag) if(!(include_mask & (long long)RANDOM_RW_MASK) || no_write) goto next6; toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[8]); if((!distributed) || (distributed && master_iozone)) start_monitor("Randwrite"); walltime = 0.0; cputime = 0.0; jstarttime=0; sync(); sleep(2); *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_RANDOM_WRITE_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(38); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_ranwrite_test((int)xx); #else thread_ranwrite_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_ranwrite_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_ranwrite_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(39); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the biggest walltime */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld random writers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld random writers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld random writers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld random writers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Randwrite"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next6: /**************************************************************/ /*** Pwrite writer throughput tests **************************/ /**************************************************************/ #ifndef HAVE_PREAD goto next7; #else if(include_tflag) if(!(include_mask & (long long)PWRITER_MASK)) goto next7; toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[9]); if((!distributed) || (distributed && master_iozone)) start_monitor("Pwrite"); walltime = 0.0; cputime = 0.0; jstarttime=0; sync(); sleep(2); *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_PWRITE_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(38); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_pwrite_test((int)xx); #else thread_pwrite_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_pwrite_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_pwrite_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(39); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the biggest walltime*/ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld pwrite writers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld pwrite writers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld pwrite writers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld pwrite writers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Pwrite"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } #endif /**************************************************************/ /*** Pread reader throughput tests **************************/ /**************************************************************/ next7: #ifndef HAVE_PREAD goto next8; #else if(include_tflag) if(!(include_mask & (long long)PREADER_MASK)) goto next8; toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[10]); if((!distributed) || (distributed && master_iozone)) start_monitor("Pread"); walltime = 0.0; cputime = 0.0; jstarttime=0; sync(); sleep(2); *stop_flag=0; total_kilos=0; /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_PREAD_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(38); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_pread_test((int)xx); #else thread_pread_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_pread_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_pread_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(39); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); } getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ /* wait for children to stop */ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the biggest walltime*/ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %ld pread readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %ld pread readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %lld pread readers \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %lld pread readers \t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Pread"); sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } #endif next8: if(include_tflag) if(!(include_mask & (long long)FWRITER_MASK)) goto next9; /**************************************************************/ /*** fwriter throughput tests *********************************/ /**************************************************************/ if((!distributed) || (distributed && master_iozone)) start_monitor("Fwrite"); toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[11]); walltime = 0.0; cputime = 0.0; jstarttime=0; total_kilos=0; if(distributed) { use_thread=0; if(master_iozone) master_listen_socket=start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_FWRITE_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(30); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_fwrite_test((int)xx); #else thread_fwrite_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_fwrite_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_fwrite_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(31); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); goto jumpend1; } jumpend1: getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %2ld fwriters \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2ld fwriters \t\t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %2lld fwriters \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2lld fwriters \t\t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Fwrite"); /**********************************************************/ /*************** End of fwrite throughput ****************/ /**********************************************************/ sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next9: if(include_tflag) if(!(include_mask & (long long)FREADER_MASK)) goto next10; /**************************************************************/ /*** freader throughput tests *********************************/ /**************************************************************/ if((!distributed) || (distributed && master_iozone)) start_monitor("Fread"); toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[12]); walltime = 0.0; cputime = 0.0; jstarttime=0; total_kilos=0; if(distributed) { use_thread=0; if(master_iozone) master_listen_socket=start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_FREAD_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(30); } if(childids[xx]==0){ #ifdef _64BIT_ARCH_ thread_fread_test((int)xx); #else thread_fread_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ if(!barray[xx]) { barray[xx]=(char *) alloc_mem((long long)(MAXBUFFERSIZE+cache_size),(int)0); if(barray[xx] == 0) { perror("Memory allocation failed:"); exit(26); } barray[xx] =(char *)(((long)barray[xx] + cache_size ) & ~(cache_size-1)); } #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_fread_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_fread_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ kill((pid_t)myid,(int)SIGTERM); } exit(31); } } } #endif if(myid == (long long)getpid()){ if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } starttime1 = time_so_far(); goto jumpend3; } jumpend3: getout=0; if(myid == (long long)getpid()){ /* Parent here */ for( i = 0; i < num_child; i++){ child_stat = (struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest running:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } if(!jstarttime) jstarttime = time_so_far(); } jtime = (time_so_far()-jstarttime)-time_res; if(jtime < (double).000001) { jtime=time_res; } } total_time = (time_so_far() - starttime1)-time_res; /* Parents time */ if(total_time < (double).000001) { total_time=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } #ifdef JTIME total_time=total_time-jtime;/* Remove the join time */ if(!silent) printf("\nJoin time %10.2f\n",jtime); #endif total_kilos=0; ptotal=0; min_throughput=max_throughput=min_xfer=0; if(!silent) printf("\n"); for(xyz=0;xyzthroughput; ptotal+=child_stat->actual; if(!min_xfer) min_xfer=child_stat->actual; if(child_stat->actual < min_xfer) min_xfer=child_stat->actual; if(!min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput < min_throughput) min_throughput=child_stat->throughput; if(child_stat->throughput > max_throughput) max_throughput=child_stat->throughput; cputime += child_stat->cputime; /* Get the earliest start time and latest fini time to calc. elapsed time. */ if (child_stat->walltime < child_stat->cputime) child_stat->walltime = child_stat->cputime; if (child_stat->walltime > walltime) walltime = child_stat->walltime; } avg_throughput=total_kilos/num_child; if(cpuutilflag) { if (cputime < cputime_res) cputime = 0.0; } if(cpuutilflag) store_times (walltime, cputime); /* Must be Before store_dvalue(). */ store_dvalue(total_kilos); #ifdef NO_PRINT_LLD if(!silent) printf("\tChildren see throughput for %2ld freaders \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2ld freaders \t\t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #else if(!silent) printf("\tChildren see throughput for %2lld freaders \t= %10.2f %s/sec\n", num_child, total_kilos,unit); if(!silent && !distributed) printf("\tParent sees throughput for %2lld freaders \t\t= %10.2f %s/sec\n", num_child, (double)(ptotal)/total_time,unit); #endif if(!silent) printf("\tMin throughput per %s \t\t\t= %10.2f %s/sec \n", port,min_throughput,unit); if(!silent) printf("\tMax throughput per %s \t\t\t= %10.2f %s/sec\n", port,max_throughput,unit); if(!silent) printf("\tAvg throughput per %s \t\t\t= %10.2f %s/sec\n", port,avg_throughput,unit); if(!silent) printf("\tMin xfer \t\t\t\t\t= %10.2f %s\n", min_xfer,unit); /* CPU% can be > 100.0 for multiple CPUs */ if(cpuutilflag) { if(walltime == 0.0) { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 0.0); } else { if(!silent) printf("\tCPU utilization: Wall time %8.3f CPU time %8.3f CPU utilization %6.2f %%\n\n", walltime, cputime, 100.0 * cputime / walltime); } } if(Cflag) { for(xyz=0;xyzactual, unit, child_stat->throughput, unit, child_stat->walltime, child_stat->cputime, cpu_util(child_stat->cputime, child_stat->walltime)); } else { if(!silent) printf("\tChild[%ld] xfer count = %10.2f %s, Throughput = %10.2f %s/sec\n", (long)xyz, child_stat->actual, unit, child_stat->throughput, unit); } } } if((!distributed) || (distributed && master_iozone)) stop_monitor("Fread"); /**********************************************************/ /*************** End of fread throughput ******************/ /**********************************************************/ sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } next10: sleep(2); /* You need this. If you stop and restart the master_listen it will fail on Linux */ if (!no_unlink) { /**********************************************************/ /* Cleanup all of the temporary files */ /* This is not really a test. It behaves like a test so */ /* it can unlink all of the same files that the other */ /* tests left hanging around. */ /**********************************************************/ /* Hooks to start the distributed Iozone client/server code */ if(distributed) { use_thread=0; /* Turn of any Posix threads */ if(master_iozone) master_listen_socket = start_master_listen(); else become_client(); } if(!use_thread) { for(xx = 0; xx< num_child ; xx++){ chid=xx; childids[xx] = start_child_proc(THREAD_CLEANUP_TEST,numrecs64,reclen); if(childids[xx]==-1){ printf("\nFork failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)childids[xy],(long long)SIGTERM); } exit(28); } if(childids[xx] == 0){ #ifdef _64BIT_ARCH_ thread_cleanup_test((int)xx); #else thread_cleanup_test((int)xx); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ #ifdef _64BIT_ARCH_ childids[xx] = mythread_create((void *)thread_cleanup_test,(int)xx); #else childids[xx] = mythread_create((void *)thread_cleanup_test,(int)xx); #endif if(childids[xx]==-1){ printf("\nThread create failed\n"); for(xy = 0; xy< xx ; xy++){ Kill((long long)myid,(long long)SIGTERM); } exit(29); } } } #endif if((long long)myid == getpid()) { if(distributed && master_iozone) { start_master_listen_loop((int) num_child); } for(i=0;iflag==CHILD_STATE_HOLD) Poll((long long)1); } for(i=0;iflag = CHILD_STATE_BEGIN; /* tell children to go */ if(delay_start!=0) Poll((long long)delay_start); if(distributed && master_iozone) tell_children_begin(i); } } getout=0; if((long long)myid == getpid()){ /* Parent only here */ for( i = 0; i < num_child; i++){ child_stat=(struct child_stats *)&shmaddr[i]; if(distributed && master_iozone) { printf("\n\tTest cleanup:"); wait_dist_join(); break; } else { if(use_thread) { thread_join(childids[i],(void *)&pstatus); } else { wait(0); } } } } for(xyz=0;xyzflag = CHILD_STATE_HOLD; } sync(); sleep(2); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); #ifdef Windows /* windows needs time before shutting down sockets */ sleep(1); #endif cleanup_comm(); } } #ifndef NO_THREADS /* Destroy the barrier */ pthread_barrier_destroy(barrier); #endif /********************************************************/ /* End of cleanup */ /********************************************************/ sync(); if(!silent) printf("\n"); if(!silent) printf("\n"); return; } /************************************************************************/ /* Time measurement routines. */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double time_so_far(void) #else static double time_so_far() #endif { #ifdef Windows LARGE_INTEGER freq,counter; double wintime,bigcounter; struct timeval tp; /* For Windows the time_of_day() is useless. It increments in 55 milli * second increments. By using the Win32api one can get access to the * high performance measurement interfaces. With this one can get back * into the 8 to 9 microsecond resolution. */ if(pit_hostname[0]){ if (pit_gettimeofday(&tp, (struct timezone *) NULL, pit_hostname, pit_service) == -1) perror("pit_gettimeofday"); return ((double) (tp.tv_sec)) + (((double) tp.tv_usec) * 0.000001 ); } else { QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&counter); bigcounter=(double)counter.HighPart *(double)0xffffffff + (double)counter.LowPart; wintime = (double)(bigcounter/(double)freq.LowPart); return((double)wintime); } #else #if defined (OSFV4) || defined(OSFV3) || defined(OSFV5) struct timespec gp; if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1) perror("getclock"); return (( (double) (gp.tv_sec)) + ( ((float)(gp.tv_nsec)) * 0.000000001 )); #else struct timeval tp; if(pit_hostname[0]){ if (pit_gettimeofday(&tp, (struct timezone *) NULL, pit_hostname, pit_service) == -1) perror("pit_gettimeofday"); return ((double) (tp.tv_sec)) + (((double) tp.tv_usec) * 0.000001 ); } else { if (gettimeofday(&tp, (struct timezone *) NULL) == -1) perror("gettimeofday"); return ((double) (tp.tv_sec)) + (((double) tp.tv_usec) * 0.000001 ); } #endif #endif } /************************************************************************/ /* FETCHIT () */ /* */ /* Routine to make the on chip data cache hot for this buffer. The */ /* on chip cache may have been blown by other code in the application */ /* or in the OS. Remember, on some machines, the data cache is direct */ /* mapped and virtual indexed. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void fetchit(char *buffer,long long length) #else void fetchit(buffer,length) char *buffer; long long length; #endif { char *where; volatile long long x[4]; long long i; where=(char *)buffer; if(cache_line_size == 0) /* This shouldn't be needed */ cache_line_size=MY_CACHE_LINE_SIZE; for(i=0;i<(length/cache_line_size);i++) { x[(i & 3)]=*(where); where+=cache_line_size; } } /************************************************************************/ /* Verify that the buffer contains expected pattern */ /************************************************************************/ /* sverify == 0 means full check of pattern for every byte. */ /* severify == 1 means partial check of pattern for each page. */ /* sverify == 2 means no check, but partial touch for each page. */ /************************************************************************/ #ifdef HAVE_ANSIC_C long long verify_buffer(volatile char *buffer,long long length, off64_t recnum, long long recsize,unsigned long long patt, char sverify) #else long long verify_buffer(buffer,length, recnum, recsize,patt,sverify) char *buffer; long long length; off64_t recnum; long long recsize; unsigned long long patt; char sverify; #endif { volatile unsigned long long *where; volatile unsigned long long dummy; long *de_ibuf, *de_obuf; long long j,k; off64_t file_position=0; off64_t i; char *where2; char *pattern_ptr; long long mpattern,xx2; unsigned int seed; unsigned long x; unsigned long long value,value1; unsigned long long a= 0x01020304; unsigned long long b = 0x05060708; unsigned long long c= 0x01010101; unsigned long long d = 0x01010101; unsigned long long pattern_buf; int lite = 1; /* Only validate 1 long when running de-deup validation */ value = (a<<32) | b; value1 = (c<<32) | d; /* printf("Verify Sverify %d verify %d diag_v %d\n",sverify,verify,diag_v); */ x=0; xx2=chid; if(share_file) xx2=(long long)0; mpattern=patt; pattern_buf=patt; where=(unsigned long long *)buffer; if(sverify == 2) { for(i=0;i<(length);i+=page_size) { dummy = *where; where+=(page_size/sizeof(long long)); } return(0); } if(dedup_flag) { gen_new_buf((char *)dedup_ibuf,(char *)dedup_temp, (long)recnum, (int)length,(int)dedup, (int) dedup_interior, dedup_compress, 0); de_ibuf = (long *)buffer; de_obuf = (long *)dedup_temp; if(lite) /* short touch to reduce intrusion */ length = (long long) sizeof(long); for(i=0;i<(off64_t) (length/sizeof(long));i++) { if(de_ibuf[i]!= de_obuf[i]) { if(!silent) #ifdef NO_PRINT_LLD printf("\nDedup mis-compare at %ld\n", (long long)((recnum*recsize)+(i*sizeof(long))) ); #else printf("\nDedup mis-compare at %lld\n", (long long)((recnum*recsize)+(i*sizeof(long))) ); printf("Found %.lx Expecting %.lx \n",de_ibuf[i], de_obuf[i]); #endif return(1); } } return(0); } if(diag_v) { if(no_unlink) base_time=0; seed= (unsigned int)(base_time+xx2+recnum); srand(seed); mpattern=(long long)rand(); mpattern=(mpattern<<48) | (mpattern<<32) | (mpattern<<16) | mpattern; mpattern=mpattern+value; } /* printf("verify patt %llx CHid %d\n",mpattern,chid);*/ where=(unsigned long long *)buffer; if(!verify) printf("\nOOPS You have entered verify_buffer unexpectedly !!! \n"); if(sverify == 1) { for(i=0;i<(length);i+=page_size) { if((unsigned long long)(*where) != (unsigned long long)((pattern_buf<<32) | pattern_buf)) { file_position = (off64_t)( (recnum * recsize)+ i); printf("\n\n"); #ifdef NO_PRINT_LLD printf("Error in file: Found ?%lx? Expecting ?%lx? addr %lx\n",*where, (long long)((pattern_buf<<32)|pattern_buf),where); printf("Error in file: Position %ld \n",(long long)file_position); printf("Record # %ld Record size %ld kb \n",(long long)recnum,(long long)recsize/1024); printf("where %8.8lx loop %ld\n",where,i); #else printf("Error in file: Found ?%llx? Expecting ?%llx? addr %lx\n",(long long )(*where), (long long)((pattern_buf<<32)|pattern_buf),((long)where)); printf("Error in file: Position %lld \n",(long long)file_position); printf("Record # %lld Record size %lld kb \n",(long long)recnum,(long long)recsize/1024); printf("where %px loop %lld\n",where,(long long)i); #endif return(1); } where+=(page_size/sizeof(long long)); } } if(sverify == 0) { for(i=0;i<(length/cache_line_size);i++) { for(j=0;j<(long long)(cache_line_size/sizeof(long long));j++) { if(diag_v) { pattern_buf=mpattern; } else { pattern_buf= mpattern<<32 | mpattern; } pattern_ptr =(char *)&pattern_buf; if(*where != (unsigned long long)pattern_buf) { file_position = (off64_t)( (recnum * recsize))+ ((i*cache_line_size)+(j*sizeof(long long))); where2=(char *)where; for(k=0;k<(long long)(sizeof(long long));k++){ if(*where2 != *pattern_ptr) break; where2++; pattern_ptr++; } file_position+=k; printf("\n\n"); #ifdef NO_PRINT_LLD printf("Error in file: Position %ld %ld %ld \n",(long long)i,(long long)j,(long long)k); printf("Error in file: Position %ld \n",(long long)file_position); printf("Record # %ld Record size %ld kb \n",(long long)recnum,(long long)recsize/1024); #else printf("Error in file: Position %lld %lld %lld \n",(long long)i,(long long)j,(long long)k); printf("Error in file: Position %lld \n",(long long)file_position); printf("Record # %lld Record size %lld kb \n",(long long)recnum,(long long)recsize/1024); #endif printf("Found pattern: Char >>%c<< Expecting >>%c<<\n", *where2,*pattern_ptr); printf("Found pattern: Hex >>%x<< Expecting >>%x<<\n", *where2,*pattern_ptr); return(1); } where++; if(diag_v) mpattern=mpattern+value1; } } } return(0); } /************************************************************************/ /* Fill the buffer */ /************************************************************************/ #ifdef HAVE_ANSIC_C void fill_buffer(char *buffer,long long length,long long pattern,char sverify,long long recnum) #else void fill_buffer(buffer,length,pattern,sverify,recnum) char *buffer; long long length; long long pattern; long long recnum; char sverify; #endif { unsigned long long *where; long long i,j,xx2; long long mpattern; unsigned int seed; unsigned long x; unsigned long long value,value1; unsigned long long a = 0x01020304; unsigned long long b = 0x05060708; unsigned long long c = 0x01010101; unsigned long long d = 0x01010101; value = (a << 32) | b; value1 = (c << 32) | d; xx2=chid; if(share_file) xx2=(long long)0; x=0; mpattern=pattern; /* printf("Fill: Sverify %d verify %d diag_v %d\n",sverify,verify,diag_v);*/ if(dedup_flag) { gen_new_buf((char *)dedup_ibuf,(char *)buffer, (long)recnum, (int)length,(int)dedup, (int) dedup_interior, dedup_compress, 1); return; } if(diag_v) { /*if(client_iozone) base_time=0; */ if(no_unlink) base_time=0; seed= (unsigned int)(base_time+xx2+recnum); srand(seed); mpattern=(long long)rand(); mpattern=(mpattern<<48) | (mpattern<<32) | (mpattern<<16) | mpattern; mpattern=mpattern+value; } where=(unsigned long long *)buffer; if(sverify == 1) { for(i=0;i<(length);i+=page_size) { *where = (long long)((pattern<<32) | pattern); where+=(page_size/sizeof(long long)); /* printf("Filling page %lld \n",i/page_size);*/ } } else { for(i=0;i<(length/cache_line_size);i++) { for(j=0;j<(long long)((cache_line_size/sizeof(long long)));j++) { if(diag_v) { *where = (long long)(mpattern); mpattern=mpattern+value1; } else *where = (long long)((pattern<<32) | pattern); where++; } } } } /************************************************************************/ /* PURGEIT() */ /* */ /* Routine to make the on chip data cache cold for this buffer. */ /* Remember, on some machines, the data cache is direct mapped and */ /* virtual indexed. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void purgeit(char *buffer,long long reclen) #else void purgeit(buffer,reclen) char *buffer; long long reclen; #endif { char *where; long rsize; long tsize; VOLATILE long long x[200]; long i,cache_lines_per_rec; long cache_lines_per_cache; tsize = 200; cache_lines_per_rec = (long)(reclen/cache_line_size); cache_lines_per_cache = (long)(cache_size/cache_line_size); rsize = (long)l_min((long long)cache_lines_per_rec,(long long)cache_lines_per_cache); #ifdef _64BIT_ARCH_ where=(char *)pbuffer + ((unsigned long long)buffer & (cache_size-1)); #else where=(char *)pbuffer + ((long)buffer & ((long)cache_size-1)); #endif for(i=0;i<(rsize);i++) { x[i%tsize]=*(where); where+=cache_line_size; } } #ifdef HAVE_ANSIC_C void prepage(char *buffer,long long reclen) #else void prepage(buffer, reclen) char *buffer; long long reclen; #endif { char *where; long long i; where=(char *)buffer; for(i=0;i<(reclen/cache_line_size);i++) { *(where)=PATTERN; where+=cache_line_size; } } /************************************************************************/ /* write_perf_test () */ /* Write and re-write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void write_perf_test(off64_t kilo64,long long reclen ,long long *data1,long long *data2) #else void write_perf_test(kilo64,reclen ,data1,data2) off64_t kilo64; long long reclen; long long *data1; long long *data2; #endif { double burst_sleep_time_till_now[2] = {0, 0}; double starttime1; double writetime[2]; double walltime[2], cputime[2]; double qtime_start,qtime_stop; double hist_time; double compute_val = (double)0; #ifdef unix double qtime_u_start,qtime_u_stop; double qtime_s_start,qtime_s_stop; #endif long long i,j; off64_t numrecs64,traj_offset; off64_t lock_offset=0; long long Index = 0; int file_flags = 0; long long traj_size; unsigned long long writerate[2]; off64_t filebytes64; int ltest; char *maddr; char *wmaddr,*free_addr; char *pbuff; char *nbuff; int fd,wval; #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif int test_foo; #ifdef unix qtime_u_start=qtime_u_stop=0; qtime_s_start=qtime_s_stop=0; #endif nbuff=wmaddr=free_addr=0; traj_offset=0; test_foo=0; hist_time=qtime_start=qtime_stop=0; maddr=0; pbuff=mainbuffer; if(w_traj_flag) { filebytes64 = w_traj_fsize; numrecs64=w_traj_ops; } else { numrecs64 = (kilo64*1024)/reclen; filebytes64 = numrecs64*reclen; } if(Q_flag && (!wol_opened)) { wol_opened++; wqfd=fopen("wol.dat","a"); if(wqfd==0) { printf("Unable to open wol.dat\n"); exit(40); } fprintf(wqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); rwqfd=fopen("rwol.dat","a"); if(rwqfd==0) { printf("Unable to open rwol.dat\n"); exit(41); } fprintf(rwqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } fd = 0; if(oflag) file_flags = O_RDWR|O_SYNC; else file_flags = O_RDWR; #if defined(O_DSYNC) if(odsync) file_flags |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) || defined(__FreeBSD__) || defined(__DragonFly__) if(read_sync) file_flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) file_flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) file_flags |=O_DIRECTIO; #endif #endif /* Sanity check */ /* Some filesystems do not behave correctly and fail * when this sequence is performned. This is a very * bad thing. It breaks many applications and lurks * around quietly. This code should never get * triggered, but in the case of running iozone on * an NFS client, the filesystem type on the server * that is being exported can cause this failure. * If this failure happens, then the NFS client is * going to going to have problems, but the acutal * problem is the filesystem on the NFS server. * It's not NFS, it's the local filesystem on the * NFS server that is not correctly permitting * the sequence to function. */ /* _SUA_ Services for Unix Applications, under Windows does not have a truncate, so this must be skipped */ #if !defined(_SUA_) if((fd = I_OPEN(filename, (int)O_CREAT|O_WRONLY,0))<0) { printf("\nCan not open temp file: %s\n", filename); perror("open"); exit(44); } if(!notruncate) { if(check_filename(filename)) { wval=ftruncate(fd,0); if(wval < 0) { printf("\n\nSanity check failed. Do not deploy this filesystem in a production environment !\n"); exit(44); } } close(fd); if(check_filename(filename)) unlink(filename); } /* Sanity check */ #endif if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; pbuff = mbuffer + Index; if(diag_v) { if(verify || dedup_flag || dedup_iflag) fill_buffer(pbuff,reclen,(long long)pattern,sverify,(long long)i); } else { if(verify || dedup_flag || dedup_iflag) fill_buffer(pbuff,reclen,(long long)pattern,sverify,(long long)0); } } if(async_flag && no_copy_flag) { free_addr=nbuff=(char *)malloc((size_t)reclen+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,i); if(purge) purgeit(nbuff,reclen); } if(purge) purgeit(pbuff,reclen); if(Q_flag || hist_summary) { qtime_start=time_so_far(); } if(mmapflag) { wmaddr = &maddr[i*reclen]; fill_area((long long*)pbuff,(long long*)wmaddr,(long long)reclen); if(!mmapnsflag) { if(mmapasflag) msync(wmaddr,(size_t)reclen,MS_ASYNC); if(mmapssflag) msync(wmaddr,(size_t)reclen,MS_SYNC); } } else { if(async_flag) { if(no_copy_flag) async_write_no_copy(gc, (long long)fd, nbuff, reclen, (i*reclen), depth,free_addr); else async_write(gc, (long long)fd, pbuff, reclen, (i*reclen), depth); } else { #if defined(Windows) if(unbuffered) { WriteFile(hand, pbuff, reclen,(LPDWORD)&wval, 0); } else { #endif wval=write(fd, pbuff, (size_t ) reclen); if(wval != reclen) { #ifdef NO_PRINT_LLD printf("\nError writing block %ld, fd= %d\n", i, fd); #else printf("\nError writing block %lld, fd= %d\n", i, fd); #endif if(wval == -1) perror("write"); exit_code = 74; signal_handler(); } #if defined(Windows) } #endif /* The burst work does not work for async or memory * mapped IO */ if (wval != -1) update_burst_sleep(fd, wval, &burst_sleep_time_till_now[j]); } } if(hist_summary) { qtime_stop=time_so_far(); hist_time =(qtime_stop-qtime_start-time_res); hist_insert(hist_time); } if(Q_flag) { qtime_stop=time_so_far(); if(j==0) #ifdef NO_PRINT_LLD fprintf(wqfd,"%10.1ld %10.0f %10.1ld\n",(long long)(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,(long long)reclen); else fprintf(rwqfd,"%10.1ld %10.0f %10.1ld\n",(long long)(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,(long long)reclen); #else fprintf(wqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,(long long)reclen); else fprintf(rwqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,(long long)reclen); #endif } w_traj_ops_completed++; w_traj_bytes_completed+=reclen; if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } } #ifdef unix if(Q_flag) { qtime_u_stop=utime_so_far(); qtime_s_stop=stime_so_far(); if(j==0) fprintf(wqfd,"\nSystem time %10.3f User time %10.3f Real %10.3f (seconds)\n", (qtime_s_stop-qtime_s_start)/sc_clk_tck, (qtime_u_stop-qtime_u_start)/sc_clk_tck, time_so_far()-starttime1); else fprintf(rwqfd,"\nSystem time %10.3f User time %10.3f Real %10.3f (seconds)\n", (qtime_s_stop-qtime_s_start)/sc_clk_tck, (qtime_u_stop-qtime_u_start)/sc_clk_tck, time_so_far()-starttime1); } #endif #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag){ msync(maddr,(size_t)filebytes64,MS_SYNC); } else { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } } if(file_lock) if(mylockf((int) fd,(int)0,(int)0)) printf("Unlock failed %d\n",errno); if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(inc_think) writetime[j] = ((time_so_far() - starttime1)-time_res - burst_sleep_time_till_now[j]); else writetime[j] = ((time_so_far() - starttime1)-time_res - burst_sleep_time_till_now[j]) -compute_val; if(writetime[j] < (double).000001) { writetime[j]=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC);/* Clean up before read starts */ else { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } if(OPS_flag || MS_flag){ filebytes64=w_traj_ops_completed; /*filebytes64=filebytes64/reclen;*/ }else filebytes64=w_traj_bytes_completed; for(j=0;j>= 10; } data1[0]=writerate[0]; if(noretest) { writerate[1]=(long long) 0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)writerate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)writerate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",writerate[0]); if(!silent) printf("%9ld",writerate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",writerate[0]); if(!silent) printf("%9lld",writerate[1]); if(!silent) fflush(stdout); #endif } /************************************************************************/ /* fwrite_perf_test () */ /* fWrite and fre-write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void fwrite_perf_test(off64_t kilo64,long long reclen ,long long *data1,long long *data2) #else void fwrite_perf_test(kilo64,reclen ,data1,data2) off64_t kilo64; long long reclen; long long *data1; long long *data2; #endif { double burst_sleep_time_till_now[2] = {0, 0}; double starttime1; double writetime[2]; double walltime[2], cputime[2]; double compute_val = (double)0; long long i,j; off64_t numrecs64; long long Index = 0; unsigned long long writerate[2]; off64_t filebytes64; FILE *stream = NULL; int fd; int wval; int ltest; char *how; char *stdio_buf; if(mmapflag || async_flag) return; numrecs64 = (kilo64*1024)/reclen; filebytes64 = numrecs64*reclen; stdio_buf=(char *)malloc((size_t)reclen); if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; buffer = mbuffer + Index; } if((verify & diag_v) || dedup_flag || dedup_iflag) fill_buffer(buffer,reclen,(long long)pattern,sverify,i); if(purge) purgeit(buffer,reclen); if(fwrite(buffer, (size_t) reclen, 1, stream) != 1) { #ifdef NO_PRINT_LLD printf("\nError fwriting block %ld, fd= %d\n", i, fd); #else printf("\nError fwriting block %lld, fd= %d\n", i, fd); #endif perror("fwrite"); exit_code = 74; signal_handler(); } update_burst_sleep(fd, reclen, &burst_sleep_time_till_now[j]); } if(include_flush) { fflush(stream); wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } if(include_close) { wval=fclose(stream); if(wval==-1){ perror("fclose"); signal_handler(); } } if(inc_think) writetime[j] = ((time_so_far() - starttime1)-time_res - burst_sleep_time_till_now[j]); else writetime[j] = ((time_so_far() - starttime1)-time_res - burst_sleep_time_till_now[j]) -compute_val; if(writetime[j] < (double).000001) { writetime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { wval=fflush(stream); if(wval==-1){ perror("fflush"); signal_handler(); } wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } wval=fclose(stream); if(wval==-1){ perror("fclose"); signal_handler(); } } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)(int)rest_val); } free(stdio_buf); if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } for(j=0;j>= 10; } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(noretest) { writerate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)writerate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)writerate[1]); data1[0]=writerate[0]; #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",writerate[0]); if(!silent) printf("%9ld",writerate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",writerate[0]); if(!silent) printf("%9lld",writerate[1]); if(!silent) fflush(stdout); #endif } /************************************************************************/ /* fread_perf_test */ /* fRead and fre-read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void fread_perf_test(off64_t kilo64,long long reclen,long long *data1,long long *data2) #else void fread_perf_test(kilo64,reclen,data1,data2) off64_t kilo64; long long reclen; long long *data1,*data2; #endif { double starttime2; double readtime[2]; double walltime[2], cputime[2]; double compute_val = (double)0; long long j; off64_t i,numrecs64; long long Index = 0; unsigned long long readrate[2]; off64_t filebytes64; FILE *stream = 0; char *stdio_buf; int fd,ltest; if(mmapflag || async_flag) return; numrecs64 = (kilo64*1024)/reclen; filebytes64 = numrecs64*reclen; stdio_buf=(char *)malloc((size_t)reclen); if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; buffer = mbuffer + Index; } if(purge) purgeit(buffer,reclen); if(fread(buffer, (size_t) reclen,1, stream) != 1) { #ifdef _64BIT_ARCH_ #ifdef NO_PRINT_LLD printf("\nError freading block %lu %lx\n", (long long)i, (unsigned long long)buffer); #else printf("\nError freading block %llu %llx\n", (long long)i, (unsigned long long)buffer); #endif #else #ifdef NO_PRINT_LLD printf("\nError freading block %lu %lx\n", (long long)i, (long)buffer); #else printf("\nError freading block %llu %lx\n", (long long)i, (long)buffer); #endif #endif perror("read"); exit(54); } if(verify){ if(verify_buffer(buffer,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ exit(55); } } } if(include_flush) fflush(stream); if(include_close) { fclose(stream); } if(inc_think) readtime[j] = ((time_so_far() - starttime2)-time_res); else readtime[j] = ((time_so_far() - starttime2)-time_res) -compute_val; if(readtime[j] < (double).000001) { readtime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { fflush(stream); fclose(stream); } stream = NULL; if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } free(stdio_buf); if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } for(j=0;j>= 10; } data1[0]=readrate[0]; data2[0]=1; if(noretest) { readrate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)readrate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)readrate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",readrate[0]); if(!silent) printf("%9ld",readrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",readrate[0]); if(!silent) printf("%9lld",readrate[1]); if(!silent) fflush(stdout); #endif } /************************************************************************/ /* read_perf_test */ /* Read and re-fread test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void read_perf_test(off64_t kilo64,long long reclen,long long *data1,long long *data2) #else void read_perf_test(kilo64,reclen,data1,data2) off64_t kilo64; long long reclen; long long *data1,*data2; #endif { double starttime2; double compute_val = (double)0; double readtime[2]; double walltime[2], cputime[2]; #ifdef unix double qtime_u_start,qtime_u_stop; double qtime_s_start,qtime_s_stop; #endif long long j; long long traj_size; off64_t i,numrecs64,traj_offset; off64_t lock_offset=0; long long Index = 0; unsigned long long readrate[2]; off64_t filebytes64; volatile char *buffer1; char *nbuff; char *maddr; char *wmaddr; int fd,open_flags; int test_foo,ltest; long wval; double qtime_start,qtime_stop; double hist_time; #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif #ifdef unix qtime_u_start=qtime_u_stop=0; qtime_s_start=qtime_s_stop=0; #endif hist_time=qtime_start=qtime_stop=0; maddr=0; traj_offset=0; test_foo=0; numrecs64 = (kilo64*1024)/reclen; open_flags = O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) open_flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) open_flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) open_flags |=O_DIRECTIO; #endif #endif if(r_traj_flag) { numrecs64=r_traj_ops; filebytes64 = r_traj_fsize; } else filebytes64 = numrecs64*reclen; fd = 0; if(Q_flag && (!rol_opened)) { rol_opened++; rqfd=fopen("rol.dat","a"); if(rqfd==0) { printf("Unable to open rol.dat\n"); exit(56); } fprintf(rqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); rrqfd=fopen("rrol.dat","a"); if(rrqfd==0) { printf("Unable to open rrol.dat\n"); exit(57); } fprintf(rrqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } /* * begin real testing */ if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(purge) purgeit(nbuff,reclen); if(Q_flag || hist_summary) qtime_start=time_so_far(); if(mmapflag) { wmaddr=&maddr[i*reclen]; fill_area((long long*)wmaddr,(long long*)nbuff,(long long)reclen); } else { if(async_flag) { if(no_copy_flag) async_read_no_copy(gc, (long long)fd, &buffer1, (i*reclen), reclen, 1LL,(numrecs64*reclen),depth); else async_read(gc, (long long)fd, nbuff, (i*reclen),reclen, 1LL,(numrecs64*reclen),depth); } else { #if defined(Windows) if(unbuffered) { ReadFile(hand, nbuff, reclen,(LPDWORD)&wval, 0); } else #endif wval=read((int)fd, (void*)nbuff, (size_t) reclen); if(wval != reclen) { #ifdef _64BIT_ARCH_ #ifdef NO_PRINT_LLD printf("\nError reading block %ld %lx\n", (long)i, (unsigned long long)nbuff); #else printf("\nError reading block %lld %llx\n", (long long)i, (unsigned long long)nbuff); #endif #else #ifdef NO_PRINT_LLD printf("\nError reading block %ld %x\n", (long)i, (long)nbuff); #else printf("\nError reading block %lld %lx\n", (long long)i, (long)nbuff); #endif #endif perror("read"); exit(61); } } } if(verify) { if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ exit(62); } } else { if(verify_buffer(nbuff,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ exit(63); } } } if(async_flag && no_copy_flag) async_release(gc); buffer1=0; if(hist_summary) { qtime_stop=time_so_far(); hist_time =(qtime_stop-qtime_start-time_res); hist_insert(hist_time); } if(Q_flag) { qtime_stop=time_so_far(); if(j==0) #ifdef NO_PRINT_LLD fprintf(rqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,(long)reclen); else fprintf(rrqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,(long)reclen); #else fprintf(rqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,(long long)reclen); else fprintf(rrqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,(long long)reclen); #endif } r_traj_ops_completed++; r_traj_bytes_completed+=reclen; } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } if(file_lock) if(mylockf((int) fd, (int) 0, (int)1)) printf("Read unlock failed. %d\n",errno); #ifdef unix if(Q_flag) { qtime_u_stop=utime_so_far(); qtime_s_stop=stime_so_far(); if(j==0) fprintf(rqfd,"\nSystem time %10.3f User time %10.3f Real %10.3f (seconds)\n", (qtime_s_stop-qtime_s_start)/sc_clk_tck, (qtime_u_stop-qtime_u_start)/sc_clk_tck, time_so_far()-starttime2); else fprintf(rrqfd,"\nSystem time %10.3f User time %10.3f Real %10.3f (seconds)\n", (qtime_s_stop-qtime_s_start)/sc_clk_tck, (qtime_u_stop-qtime_u_start)/sc_clk_tck, time_so_far()-starttime2); } #endif #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } if(inc_think) readtime[j] = ((time_so_far() - starttime2)-time_res); else readtime[j] = ((time_so_far() - starttime2)-time_res)-compute_val; if(readtime[j] < (double).000001) { readtime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } if(OPS_flag || MS_flag){ filebytes64=r_traj_ops_completed; /*filebytes64=filebytes64/reclen;*/ } else filebytes64=r_traj_bytes_completed; for(j=0;j>= 10; } data1[0]=readrate[0]; data2[0]=1; if(noretest) { readrate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)readrate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)readrate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",readrate[0]); if(!silent) printf("%9ld",readrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",readrate[0]); if(!silent) printf("%9lld",readrate[1]); if(!silent) fflush(stdout); #endif } /************************************************************************/ /* random_perf_test */ /* Random read and write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void random_perf_test(off64_t kilo64,long long reclen,long long *data1,long long *data2) #else void random_perf_test(kilo64,reclen,data1,data2) off64_t kilo64; long long reclen; long long *data1, *data2; #endif { double randreadtime[2]; double starttime2; double walltime[2], cputime[2]; double compute_val = (double)0; #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; #endif unsigned long long big_rand; long long j; off64_t i,numrecs64; long long Index=0; double burst_sleep_time_till_now[2] = {0, 0}; int flags; unsigned long long randreadrate[2]; off64_t filebytes64; off64_t lock_offset=0; volatile char *buffer1; char *wmaddr,*nbuff; char *maddr,*free_addr; int fd,wval; long long *recnum= 0; #if defined(VXFS) || defined(solaris) int test_foo=0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif #ifdef MERSENNE unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}; unsigned long long length=4; #endif maddr=free_addr=0; numrecs64 = (kilo64*1024)/reclen; #ifdef MERSENNE init_by_array64(init, length); #else #ifdef bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #endif #endif #endif recnum = (long long *)malloc(sizeof(*recnum)*numrecs64); if (recnum){ /* pre-compute random sequence based on Fischer-Yates (Knuth) card shuffle */ for(i = 0; i < numrecs64; i++){ recnum[i] = i; } for(i = numrecs64-1; i >= 0; i--) { long long tmp; #ifdef MERSENNE big_rand=genrand64_int64(); #else #ifdef bsd4_2 rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); #else #ifdef Windows rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); #else big_rand = lrand48(); #endif #endif #endif big_rand = big_rand % (i+1); tmp = recnum[i]; recnum[i] = recnum[big_rand]; recnum[big_rand] = tmp; } } else { fprintf(stderr,"Random uniqueness fallback.\n"); } flags = O_RDWR; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif fd=0; if(oflag) flags |= O_SYNC; #if defined(O_DSYNC) if(odsync) flags |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif filebytes64 = numrecs64*reclen; for( j=0; j<2; j++ ) { if(j==0) flags |=O_CREAT; if (no_write && (j == 1)) continue; if(cpuutilflag) { walltime[j] = time_so_far(); cputime[j] = cputime_so_far(); } if(Uflag) /* Unmount and re-mount the mountpoint */ { purge_buffer_cache(); } if((fd = I_OPEN(filename, ((int)flags),0640))<0){ printf("\nCan not open temporary file for read/write\n"); perror("open"); exit(66); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,filebytes64,0,PROT_READ|PROT_WRITE); } nbuff=mainbuffer; if(fetchon) fetchit(nbuff,reclen); #ifdef MERSENNE init_by_array64(init, length); #else #ifdef bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #endif #endif #endif compute_val=(double)0; starttime2 = time_so_far(); if ( j==0 ){ /* start read */ for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(purge) purgeit(nbuff,reclen); if (recnum) { offset64 = reclen * (long long)recnum[i]; } else { #ifdef MERSENNE big_rand =genrand64_int64(); offset64 = reclen * (big_rand%numrecs64); #else #ifdef bsd4_2 rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); offset64 = reclen * (big_rand%numrecs64); #else #ifdef Windows rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); offset64 = reclen * (big_rand%numrecs64); #else offset64 = reclen * (lrand48()%numrecs64); #endif #endif #endif } if( !(h_flag || k_flag || mmapflag)) { if(I_LSEEK( fd, offset64, SEEK_SET )<0) { perror("lseek"); exit(68); }; } if(rlocking) { lock_offset=I_LSEEK(fd,0,SEEK_CUR); mylockr((int) fd, (int) 1, (int)1, lock_offset, reclen); } if(mmapflag) { wmaddr=&maddr[offset64]; fill_area((long long*)wmaddr,(long long*)nbuff,(long long)reclen); } else { if(async_flag) { if(no_copy_flag) async_read_no_copy(gc, (long long)fd, &buffer1, offset64,reclen, 0LL,(numrecs64*reclen),depth); else async_read(gc, (long long)fd, nbuff, (offset64),reclen, 0LL,(numrecs64*reclen),0LL); } else { if(read(fd, (void *)nbuff, (size_t)reclen) != reclen) { #ifdef NO_PRINT_LLD printf("\nError reading block at %ld\n", (long)offset64); #else printf("\nError reading block at %lld\n", (long long)offset64); #endif perror("read"); exit(70); } } } if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)offset64/reclen,reclen,(long long)pattern,sverify)){ exit(71); } } else { if(verify_buffer(nbuff,reclen,(off64_t)offset64/reclen,reclen,(long long)pattern,sverify)){ exit(72); } } } if(async_flag && no_copy_flag) async_release(gc); if(rlocking) { lock_offset=I_LSEEK(fd,0,SEEK_CUR); mylockr((int) fd, (int) 1, (int)1, lock_offset, reclen); } } } /* start write */ else { if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if (recnum) { offset64 = reclen * (long long)recnum[i]; } else { #ifdef bsd4_2 rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); offset64 = reclen * (big_rand%numrecs64); #else #ifdef Windows rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); offset64 = reclen * (big_rand%numrecs64); #else offset64 = reclen * (lrand48()%numrecs64); #endif #endif } if(async_flag && no_copy_flag) { free_addr=nbuff=(char *)malloc((size_t)reclen+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,offset64/reclen); } if(purge) purgeit(nbuff,reclen); if((verify & diag_v) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,offset64/reclen); if (!(h_flag || k_flag || mmapflag)) { I_LSEEK( fd, offset64, SEEK_SET ); } if(rlocking) { lock_offset=I_LSEEK(fd,0,SEEK_CUR); mylockr((int) fd, (int) 1, (int)0, lock_offset, reclen); } if(mmapflag) { wmaddr=&maddr[offset64]; fill_area((long long*)nbuff,(long long*)wmaddr,(long long)reclen); if(!mmapnsflag) { if(mmapasflag) msync(wmaddr,(size_t)reclen,MS_ASYNC); if(mmapssflag) msync(wmaddr,(size_t)reclen,MS_SYNC); } } else { if(async_flag) { if(no_copy_flag) async_write_no_copy(gc, (long long)fd, nbuff, reclen, offset64, depth,free_addr); else async_write(gc, (long long)fd, nbuff, reclen, offset64, depth); } else { wval=write(fd, nbuff,(size_t)reclen); if(wval != reclen) { #ifdef NO_PRINT_LLD printf("\nError writing block at %ld\n", (long)offset64); #else printf("\nError writing block at %lld\n", (long long)offset64); #endif if(wval==-1) perror("write"); exit_code = 74; signal_handler(); } if (wval != -1) update_burst_sleep(fd, wval, &burst_sleep_time_till_now[j]); } } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } } } /* end of modifications *kcollins:2-5-96 */ #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC);/* Clean up before read starts running */ else { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(inc_think) randreadtime[j] = ((time_so_far() - starttime2)-time_res - burst_sleep_time_till_now[j]); else randreadtime[j] = ((time_so_far() - starttime2)-time_res - burst_sleep_time_till_now[j])- compute_val; if(randreadtime[j] < (double).000001) { randreadtime[j]=time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { if(mmapflag) { msync(maddr,(size_t)filebytes64,MS_SYNC);/* Clean up before read starts running */ } else { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } for(j=0;j<2;j++) { if(no_write && (j==1)) { randreadrate[1] = 0.0; continue; } if(MS_flag) { randreadrate[j]=1000000.0*(randreadtime[j] / (double)filebytes64); continue; } else { randreadrate[j] = (unsigned long long) ((double) filebytes64 / randreadtime[j]); } if(!(OPS_flag || MS_flag)) randreadrate[j] >>= 10; } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)randreadrate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)randreadrate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",(long)randreadrate[0]); if(!silent) printf("%9ld",(long)randreadrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",(long long)randreadrate[0]); if(!silent) printf("%9lld",(long long)randreadrate[1]); if(!silent) fflush(stdout); #endif if(recnum) free(recnum); } /************************************************************************/ /* reverse_perf_test */ /* Reverse read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void reverse_perf_test(off64_t kilo64,long long reclen,long long *data1,long long *data2) #else void reverse_perf_test(kilo64,reclen,data1,data2) off64_t kilo64; long long reclen; long long *data1,*data2; #endif { double revreadtime[2]; double starttime2; double walltime[2], cputime[2]; double compute_val = (double)0; long long j; off64_t i,numrecs64; long long Index = 0; unsigned long long revreadrate[2]; off64_t filebytes64; off64_t lock_offset=0; int fd,open_flags; char *maddr,*wmaddr; volatile char *buffer1; int ltest; char *nbuff; #if defined(VXFS) || defined(solaris) int test_foo=0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif maddr=wmaddr=0; open_flags=O_RDONLY; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) open_flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) open_flags |=O_DIRECTIO; #endif #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) open_flags |=O_RSYNC|O_SYNC; #endif numrecs64 = (kilo64*1024)/reclen; filebytes64 = numrecs64*reclen; fd = 0; if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(purge) purgeit(nbuff,reclen); if(mmapflag) { wmaddr = &maddr[((numrecs64-1)-i)*reclen]; fill_area((long long*)wmaddr,(long long*)nbuff,(long long)reclen); } else if(async_flag) { if(no_copy_flag) async_read_no_copy(gc, (long long)fd, &buffer1, ((((numrecs64-1)-i)*reclen)), reclen, -1LL,(numrecs64*reclen),depth); else async_read(gc, (long long)fd, nbuff, (((numrecs64-1)-i)*reclen), reclen,-1LL,(numrecs64*reclen),depth); }else { if(read((int)fd, (void*)nbuff, (size_t) reclen) != reclen) { #ifdef NO_PRINT_LLD printf("\nError reading block %ld\n", (long)i); #else printf("\nError reading block %lld\n", (long long)i); #endif perror("read"); exit(79); } } if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)(numrecs64-1)-i,reclen,(long long)pattern,sverify)){ exit(80); } } else { if(verify_buffer(nbuff,reclen,(off64_t)(numrecs64-1)-i,reclen,(long long)pattern,sverify)){ exit(81); } } } if(async_flag && no_copy_flag) async_release(gc); if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } if (!(h_flag || k_flag || mmapflag)) { I_LSEEK( fd, (off64_t)-2*reclen, SEEK_CUR ); } } #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } close(fd); } if(inc_think) revreadtime[j] = ((time_so_far() - starttime2)-time_res); else revreadtime[j] = ((time_so_far() - starttime2)-time_res) -compute_val; if(revreadtime[j] < (double).000001) { revreadtime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } close(fd); } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } for(j=0;j>= 10; } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)revreadrate[0]); #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",(long)revreadrate[0]); #else if(!silent) printf("%9lld",(long long)revreadrate[0]); #endif if(!silent) fflush(stdout); } /************************************************************************/ /* rewriterec_perf_test */ /* Re-write the same record */ /************************************************************************/ #ifdef HAVE_ANSIC_C void rewriterec_perf_test(off64_t kilo64 ,long long reclen,long long *data1,long long *data2) #else void rewriterec_perf_test(kilo64 ,reclen,data1,data2) off64_t kilo64; long long reclen; long long *data1,*data2; #endif { double burst_sleep_time_till_now = 0; double writeintime; double starttime1; double walltime, cputime; double compute_val = (double)0; long long i; off64_t numrecs64; long long flags; long long Index=0; unsigned long long writeinrate; off64_t filebytes64; off64_t lock_offset=0; int fd,wval; char *maddr; char *wmaddr,*free_addr,*nbuff; #if defined(VXFS) || defined(solaris) int test_foo=0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif walltime=cputime=0; maddr=wmaddr=free_addr=nbuff=0; numrecs64 = (kilo64*1024)/reclen; filebytes64 = numrecs64*reclen; /* flags = O_RDWR|O_CREAT|O_TRUNC;*/ flags = O_RDWR|O_CREAT; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif if(oflag) flags |= O_SYNC; #if defined(O_DSYNC) if(odsync) flags |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif /* if (!no_unlink) { if(check_filename(filename)) unlink(filename); } */ if(Uflag) /* Unmount and re-mount the mountpoint */ { purge_buffer_cache(); } if((fd = I_OPEN(filename, (int)flags,0640))<0) { printf("\nCan not open temporary file %s for write.\n",filename); perror("open"); exit(84); } #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,filebytes64,1,PROT_READ|PROT_WRITE); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } nbuff=mainbuffer; mbuffer=mainbuffer; if(fetchon) fetchit(nbuff,reclen); /* wval=write(fd, nbuff, (size_t) reclen); if(wval != reclen) { #ifdef NO_PRINT_LLD printf("\nError writing block %ld, fd= %d\n", (long)0, fd); #else printf("\nError writing block %lld, fd= %d\n", (long long)0, fd); #endif if(wval==-1) perror("write"); exit_code = 74; signal_handler(); } */ if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); starttime1 = time_so_far(); if(cpuutilflag) { walltime = time_so_far(); cputime = cputime_so_far(); } for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(async_flag && no_copy_flag) { free_addr=nbuff=(char *)malloc((size_t)reclen+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); } if((verify & diag_v) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); if(purge) purgeit(nbuff,reclen); if(mmapflag) { wmaddr = &maddr[0]; fill_area((long long*)nbuff,(long long*)wmaddr,(long long)reclen); if(!mmapnsflag) { if(mmapasflag) msync(wmaddr,(size_t)reclen,MS_ASYNC); if(mmapssflag) msync(wmaddr,(size_t)reclen,MS_SYNC); } } else { if(async_flag) { if(no_copy_flag) async_write_no_copy(gc, (long long)fd, nbuff, reclen, (i*reclen), depth,free_addr); else async_write(gc, (long long)fd, nbuff, reclen, (i*reclen), depth); } else { wval=write(fd, nbuff, (size_t) reclen); if(wval != reclen) { #ifdef NO_PRINT_LLD printf("\nError writing block %ld, fd= %d\n", (long)i, fd); #else printf("\nError writing block %lld, fd= %d\n", (long long)i, fd); #endif if(wval==-1) perror("write"); exit_code = 74; signal_handler(); } if (wval != -1) update_burst_sleep(fd, wval, &burst_sleep_time_till_now); } } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } if (!(h_flag || k_flag || mmapflag)) { I_LSEEK(fd, (off64_t)0,SEEK_SET); } } #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC);/* Clean up before read starts running */ else { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } } if(include_close) { if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(inc_think) writeintime = ((time_so_far() - starttime1)-time_res); else writeintime = ((time_so_far() - starttime1)-time_res)- compute_val; if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; walltime = time_so_far() - walltime; if (walltime < cputime) walltime = cputime; } writeintime -= burst_sleep_time_till_now; if(writeintime < (double).000001) { writeintime= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC);/* Clean up before read starts running */ else { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } if(MS_flag) { writeinrate=1000000.0*(writeintime / (double)filebytes64); } else { writeinrate = (unsigned long long) ((double) filebytes64 / writeintime); } if(!(OPS_flag || MS_flag)) writeinrate >>= 10; /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime, cputime); store_value((off64_t)writeinrate); #ifdef NO_PRINT_LLD if(!silent) printf(" %9ld",(long)writeinrate); #else if(!silent) printf(" %9lld",(long long)writeinrate); #endif if(!silent) fflush(stdout); if(restf) sleep((int)rest_val); } /************************************************************************/ /* read_stride_perf_test */ /* Read with a constant stride test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void read_stride_perf_test(off64_t kilos64,long long reclen,long long *data1,long long *data2) #else void read_stride_perf_test(kilos64,reclen,data1,data2) off64_t kilos64; long long reclen; long long *data1, *data2; #endif { double strideintime; double starttime1; double compute_val = (double)0; double walltime, cputime; off64_t numrecs64,current_position; long long Index = 0; off64_t i,savepos64 = 0; unsigned long long strideinrate; off64_t filebytes64; off64_t lock_offset=0; long long uu; off64_t stripewrap=0; int fd,open_flags; volatile char *buffer1; char *nbuff; char *maddr; char *wmaddr; #if defined(VXFS) || defined(solaris) int test_foo=0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif walltime=cputime=0; nbuff=maddr=wmaddr=0; open_flags=O_RDONLY; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) open_flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) open_flags |=O_DIRECTIO; #endif #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) open_flags |=O_RSYNC|O_SYNC; #endif next64 = (off64_t)0; numrecs64 = (kilos64*1024)/reclen; filebytes64 = numrecs64*reclen; if(Uflag) /* Unmount and re-mount the mountpoint */ { purge_buffer_cache(); } if((fd = I_OPEN(filename, (int)open_flags, 0640))<0) { printf("\nCan not open temporary file for read\n"); perror("open"); exit(86); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,filebytes64,0,PROT_READ); } fsync(fd); current_position=0; nbuff=mainbuffer; mbuffer=mainbuffer; if(fetchon) fetchit(nbuff,reclen); starttime1 = time_so_far(); if(cpuutilflag) { walltime = time_so_far(); cputime = cputime_so_far(); } for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(purge) purgeit(nbuff,reclen); if(verify) { savepos64=current_position/reclen; } if(mmapflag) { wmaddr = &maddr[current_position]; fill_area((long long*)wmaddr,(long long*)nbuff,(long long)reclen); } else { if(async_flag) { if(no_copy_flag) async_read_no_copy(gc, (long long)fd, &buffer1, current_position, reclen, stride,(numrecs64*reclen),depth); else async_read(gc, (long long)fd, nbuff, current_position, reclen, stride,(numrecs64*reclen),depth); } else { if((uu=read((int)fd, (void*)nbuff, (size_t) reclen)) != reclen) { #ifdef NO_PRINT_LLD printf("\nError reading block %ld, fd= %d Filename %s Read returned %ld\n", (long)i, fd,filename,uu); printf("\nSeeked to %ld Reclen = %ld\n", (long)savepos64,(long)reclen); #else printf("\nError reading block %lld, fd= %d Filename %s Read returned %lld\n", (long long)i, fd,filename,(long long)uu); printf("\nSeeked to %lld Reclen = %lld\n", (long long)savepos64,(long long)reclen); #endif perror("read"); exit(88); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } current_position+=reclen; if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen, (off64_t)savepos64 ,reclen,(long long)pattern,sverify)){ exit(89); } } else { if(verify_buffer(nbuff,reclen, (off64_t)savepos64 ,reclen,(long long)pattern,sverify)){ exit(90); } } } if(async_flag && no_copy_flag) async_release(gc); /* This is a bit tricky. The goal is to read with a stride through the file. The problem is that you need to touch all of the file blocks. So.. the first pass through you read with a constant stride. When you hit eof then add 1 to the beginning offset of the next time through the file. The rub here is that eventually adding 1 will cause the initial start location plus the STRIDE to be beyond eof. So... when this happens the initial offset for the next pass needs to be set back to 0. */ if(current_position + (stride * reclen) >= (numrecs64 * reclen)-reclen) { current_position=0; stripewrap++; if(numrecs64 <= stride) { current_position=0; } else { current_position = (off64_t)((stripewrap)%numrecs64)*reclen; } if (!(h_flag || k_flag || mmapflag)) { if(I_LSEEK(fd,current_position,SEEK_SET)<0) { perror("lseek"); exit(91); } } } else { current_position+=(stride*reclen)-reclen; if (!(h_flag || k_flag || mmapflag)) { if(I_LSEEK(fd,current_position,SEEK_SET)<0) { perror("lseek"); exit(93); }; } } } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; walltime = time_so_far() - walltime; if (walltime < cputime) walltime = cputime; } #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } close(fd); } if(inc_think) strideintime = ((time_so_far() - starttime1)-time_res); else strideintime = ((time_so_far() - starttime1)-time_res) -compute_val; if(strideintime < (double).000001) { strideintime= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } close(fd); } if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } if(MS_flag) { strideinrate=1000000.0*(strideintime / (double)filebytes64); } else { strideinrate = (unsigned long long) ((double) filebytes64 / strideintime); } if(!(OPS_flag || MS_flag)) strideinrate >>= 10; /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime, cputime); store_value((off64_t)strideinrate); #ifdef NO_PRINT_LLD if(!silent) printf(" %9ld",(long)strideinrate); #else if(!silent) printf(" %9lld",(long long)strideinrate); #endif if(!silent) fflush(stdout); if(restf) sleep((int)rest_val); } #ifdef HAVE_PREAD /************************************************************************/ /* pwrite_perf_test */ /* pwrite and re-write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void pwrite_perf_test(off64_t kilos64,long long reclen,long long *data1,long long *data2) #else void pwrite_perf_test(kilos64,reclen,data1,data2) off64_t kilos64; long long reclen; long long *data1,*data2; #endif { double burst_sleep_time_till_now[2] = {0, 0}; double pwritetime[2]; double starttime1; double walltime[2], cputime[2]; double compute_val = (double)0; long long i,j; long long Index = 0; unsigned long long pwriterate[2]; off64_t filebytes64; long long flags_here = 0; int fd,ltest,wval; off64_t numrecs64,traj_offset; off64_t lock_offset=0; long long traj_size; #if defined(VXFS) || defined(solaris) int test_foo=0; #endif char *nbuff; traj_offset=0; nbuff=mainbuffer; if(w_traj_flag) { filebytes64 = w_traj_fsize; numrecs64=w_traj_ops; } else { numrecs64 = (kilos64*1024)/reclen; filebytes64 = numrecs64*reclen; } fd = 0; if(oflag){ flags_here = O_SYNC|O_RDWR; } else { flags_here = O_RDWR; } #if defined(O_DSYNC) if(odsync) flags_here |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags_here |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags_here |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags_here |=O_DIRECTIO; #endif #endif if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if((verify && diag_v) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,i); if(purge) purgeit(nbuff,reclen); if(I_PWRITE(fd, nbuff, reclen, traj_offset) != reclen) { #ifdef NO_PRINT_LLD printf("\nError pwriting block %ld, fd= %d\n", (long)i, fd); #else printf("\nError pwriting block %lld, fd= %d\n", (long long)i, fd); #endif perror("pwrite"); exit_code = 74; signal_handler(); } else { update_burst_sleep(fd, reclen, &burst_sleep_time_till_now[j]); } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } } if(include_flush) { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } if(include_close) { wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(inc_think) pwritetime[j] = ((time_so_far() - starttime1)-time_res - burst_sleep_time_till_now[j]); else pwritetime[j] = ((time_so_far() - starttime1)-time_res - burst_sleep_time_till_now[j]) -compute_val; if(pwritetime[j] < (double).000001) { pwritetime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } wval=close(fd); if(wval==-1){ perror("close"); signal_handler(); } } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } for(j=0;j>= 10; } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(noretest) { pwriterate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)pwriterate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)pwriterate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%8ld",(long)pwriterate[0]); if(!silent) printf("%9ld",(long)pwriterate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",(long long)pwriterate[0]); if(!silent) printf("%9lld",(long long)pwriterate[1]); if(!silent) fflush(stdout); #endif } /************************************************************************/ /* pread_perf_test */ /* pread and re-pread test */ /************************************************************************/ #ifdef HAVE_PREAD #ifdef HAVE_ANSIC_C void pread_perf_test(off64_t kilos64,long long reclen,long long *data1,long long *data2) #else void pread_perf_test(kilos64,reclen,data1,data2) off64_t kilos64; long long reclen; long long *data1, *data2; #endif { double starttime2; double preadtime[2]; double walltime[2], cputime[2]; double compute_val = (double)0; long long numrecs64,i; long long j; long long Index = 0; unsigned long long preadrate[2]; off64_t filebytes64; off64_t lock_offset=0; int fd,open_flags; int ltest; off64_t traj_offset; long long traj_size; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif char *nbuff; traj_offset=0; nbuff=mainbuffer; open_flags=O_RDONLY; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) open_flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) open_flags |=O_DIRECTIO; #endif #endif #if defined(_HPUX_SOURCE) || defined(linux) || defined(__FreeBSD__) || defined(__DragonFly__) if(read_sync) open_flags |=O_RSYNC|O_SYNC; #endif if(r_traj_flag) { filebytes64 = r_traj_fsize; numrecs64=r_traj_ops; } else { numrecs64 = (kilos64*1024)/reclen; filebytes64 = numrecs64*reclen; } fd = 0; if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(purge) purgeit(nbuff,reclen); if(I_PREAD(((int)fd), ((void*)nbuff), ((size_t) reclen),traj_offset ) != reclen) { #ifdef NO_PRINT_LLD printf("\nError reading block %ld %lx\n", (long)i,(unsigned long)nbuff); #else printf("\nError reading block %lld %lx\n", (long long)i,(unsigned long)nbuff); #endif perror("pread"); exit(103); } if(verify){ if(verify_buffer(nbuff,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ exit(104); } } if(rlocking) { lock_offset=I_LSEEK(fd,0,SEEK_CUR); mylockr((int) fd, (int) 1, (int)1, lock_offset, reclen); } } if(include_flush) fsync(fd); if(include_close) close(fd); if(inc_think) preadtime[j] = ((time_so_far() - starttime2)-time_res); else preadtime[j] = ((time_so_far() - starttime2)-time_res) -compute_val; if(preadtime[j] < (double).000001) { preadtime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { fsync(fd); close(fd); } if(cpuutilflag) { cputime[j] = cputime_so_far() - cputime[j]; if (cputime[j] < cputime_res) cputime[j] = 0.0; walltime[j] = time_so_far() - walltime[j]; if (walltime[j] < cputime[j]) walltime[j] = cputime[j]; } if(restf) sleep((int)rest_val); } filebytes64 = numrecs64*reclen; if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } for(j=0;j>= 10; } if(noretest) { preadrate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)preadrate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)preadrate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%8ld",(long)preadrate[0]); if(!silent) printf("%9ld",(long)preadrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%8lld",(long long)preadrate[0]); if(!silent) printf("%9lld",(long long)preadrate[1]); if(!silent) fflush(stdout); #endif } #endif #ifdef HAVE_PREADV /************************************************************************/ /* pwritev_perf_test */ /* pwritev and re-pwritev test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void pwritev_perf_test(off64_t kilos64,long long reclen,long long *data1,long long *data2) #else void pwritev_perf_test(kilos64,reclen,data1,data2) off64_t kilos64; long long reclen; long long *data1,*data2; #endif { int wval; double starttime1; double pwritevtime[2]; double walltime[2], cputime[2]; double compute_val = (double)0; long long list_off[PVECMAX]; long long numvecs,j,xx; unsigned long long pwritevrate[2]; off64_t filebytes64,i; off64_t numrecs64; int fd,ltest; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif long long flags_here; char *nbuff; #ifdef MERSENNE unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}, length=4; #endif numrecs64 = (kilos64*1024)/reclen; filebytes64 = numrecs64*reclen; nbuff = mainbuffer; fd = 0; if(oflag) flags_here = O_SYNC|O_RDWR; else flags_here = O_RDWR; #if defined(O_DSYNC) if(odsync) flags_here |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags_here |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags_here |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags_here |=O_DIRECTIO; #endif #endif if(noretest) ltest=1; else ltest=2; for( j=0; j>= 10; } if(noretest) { pwritevrate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)pwritevrate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)pwritevrate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%9ld",(long)pwritevrate[0]); if(!silent) printf("%10ld",(long)pwritevrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",(long long)pwritevrate[0]); if(!silent) printf("%10lld",(long long)pwritevrate[1]); if(!silent) fflush(stdout); #endif } #endif #ifdef HAVE_PREADV /**************************************************************************/ /* create_list() */ /* Creates a list of PVECMAX entries that are unique (non over lapping ). */ /* Each of these offsets are then used in a vector (preadv/pwritev) */ /**************************************************************************/ #ifdef HAVE_ANSIC_C void create_list(long long *list_off, long long reclen, off64_t numrecs64) #else void create_list(list_off, reclen, numrecs64) long long *list_off; long long reclen; off64_t numrecs64; #endif { long long found,i,j; long long numvecs; unsigned long long big_rand = -1; #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; #endif numvecs = PVECMAX; if(numrecs64< numvecs) numvecs = numrecs64; for(j=0;j>= 10; } if(noretest) { preadvrate[1]=(long long)0; if(cpuutilflag) { walltime[1]=0.0; cputime[1]=0.0; } } /* Must save walltime & cputime before calling store_value() for each/any cell.*/ if(cpuutilflag) store_times(walltime[0], cputime[0]); store_value((off64_t)preadvrate[0]); if(cpuutilflag) store_times(walltime[1], cputime[1]); store_value((off64_t)preadvrate[1]); #ifdef NO_PRINT_LLD if(!silent) printf("%10ld",(long)preadvrate[0]); if(!silent) printf("%9ld",(long)preadvrate[1]); if(!silent) printf("\n"); if(!silent) fflush(stdout); #else if(!silent) printf("%10lld",(long long)preadvrate[0]); if(!silent) printf("%9lld",(long long)preadvrate[1]); if(!silent) printf("\n"); if(!silent) fflush(stdout); #endif } #endif /************************************************************************/ /* print_header() */ /* Prints the header for the output from Iozone. */ /************************************************************************/ #endif #ifdef HAVE_ANSIC_C void print_header(void) #else void print_header() #endif { if(Eflag) { if(!silent) printf(CONTROL_STRING2, " ", " ", " ", " ", " ", " ", "random", /*kcollins:2-5-96*/ "random", /*kcollins:2-5-96*/ "bkwd", "record", "stride", " ", " ", " ", " " #ifdef HAVE_PREAD ," ", " ", " ", " " #ifdef HAVE_PREADV ," ", " ", " ", " " #endif #endif ); if(!silent) printf(CONTROL_STRING2, "kB", "reclen", "write", "rewrite", "read", "reread", "read", /*kcollins:2-5-96*/ "write", /*kcollins:2-5-96*/ "read", "rewrite", "read", "fwrite", "frewrite", "fread", "freread" #ifdef HAVE_PREAD ,"pwrite", "repwrite", "pread", "repread" #ifdef HAVE_PREADV ,"pwritev", "repwritev", "preadv", "repreadv" #endif #endif ); }else if(RWONLYflag){ /*kcollins 8-21-96*/ if(!silent) printf(CONTROL_STRING4, /*kcollins 8-21-96*/ " ", /*kcollins 8-21-96*/ " ", /*kcollins 8-21-96*/ " ", /*kcollins 8-21-96*/ " ", /*kcollins 8-21-96*/ " ", /*kcollins 8-21-96*/ " " /*kcollins 8-21-96*/ ); /*kcollins 8-21-96*/ if(!silent) printf(CONTROL_STRING4, /*kcollins 8-21-96*/ "kB", /*kcollins 8-21-96*/ "reclen", /*kcollins 8-21-96*/ "write", /*kcollins 8-21-96*/ "rewrite", /*kcollins 8-21-96*/ "read", /*kcollins 8-21-96*/ "reread" /*kcollins 8-21-96*/ ); /*kcollins 8-21-96*/ }else{ if(!(mmapflag || async_flag)) { if(!silent) printf(CONTROL_STRING3, " ", " ", " ", " ", " ", " ", "random", /*kcollins:2-5-96*/ "random", /*kcollins:2-5-96*/ "bkwd", "record", "stride", "", "", "", "" ); if(!silent) printf(CONTROL_STRING3, "kB", "reclen", "write", "rewrite", "read", "reread", "read", /*kcollins:2-5-96*/ "write", /*kcollins:2-5-96*/ "read", "rewrite", "read", "fwrite", "frewrite", "fread", "freread" ); }else { if(!silent) printf(CONTROL_STRING3, " ", " ", " ", " ", " ", " ", "random", /*kcollins:2-5-96*/ "random", /*kcollins:2-5-96*/ "bkwd", "record", "stride", "", "", "", "" ); if(!silent) printf(CONTROL_STRING3, "kB", "reclen", "write", "rewrite", "read", "reread", "read", /*kcollins:2-5-96*/ "write", /*kcollins:2-5-96*/ "read", "rewrite", "read", "", "", "", "" ); } } } /************************************************************************/ /* store_value() */ /* Stores a value in an in memory array. Used by the report function */ /* to re-organize the output for Excel */ /************************************************************************/ #ifdef HAVE_ANSIC_C void store_value(off64_t value) #else store_value(value) off64_t value; #endif { report_array[current_x][current_y]=value; current_x++; if(current_x > max_x) max_x=current_x; if(current_y > max_y) max_y=current_y; if(max_x >= MAX_X) { printf("\nMAX_X too small\n"); exit(117); } if(max_y >= MAX_Y) { printf("\nMAX_Y too small\n"); exit(118); } } /************************************************************************/ /* store_times() */ /* Stores runtime (walltime & cputime) in a memory array. */ /* Used by the report function to re-organize the output for Excel */ /* For now, must be called immediately before calling store_value() for */ /* each cell. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void store_times(double walltime, double cputime) #else store_times(walltime, cputime) double walltime, cputime; #endif { runtimes [current_x][current_y].walltime = walltime; runtimes [current_x][current_y].cputime = cputime; runtimes [current_x][current_y].cpuutil = cpu_util(cputime, walltime); } /************************************************************************/ /* dump_report() */ /* Dumps the Excel report on standard output. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void dump_report(long long who) #else dump_report(who) long long who; #endif { long long i; off64_t current_file_size; off64_t rec_size; if(bif_flag) bif_column++; if(!silent) printf(" "); /* * Need to reconstruct the record size list * as the crossover in -a changed the list. */ del_record_sizes(); init_record_sizes(orig_min_rec_size, orig_max_rec_size); for(rec_size=get_next_record_size(0); rec_size <= orig_max_rec_size; rec_size=get_next_record_size(rec_size)) { if (rec_size == 0) break; if(bif_flag) do_float(bif_fd,(double)(rec_size/1024),bif_row,bif_column++); #ifdef NO_PRINT_LLD if(!silent) printf(" %c%ld%c",'"',(long)(rec_size/1024),'"'); #else if(!silent) printf(" %c%lld%c",'"',(long long)(rec_size/1024),'"'); #endif } if(!silent) printf("\n"); if(bif_flag) { bif_column=0; bif_row++; } current_file_size = report_array[0][0]; if(bif_flag) { do_float(bif_fd,(double)(current_file_size),bif_row,bif_column++); } #ifdef NO_PRINT_LLD if(!silent) printf("%c%ld%c ",'"',(long)current_file_size,'"'); #else if(!silent) printf("%c%lld%c ",'"',(long long)current_file_size,'"'); #endif for(i=0;i<=max_y;i++){ if(report_array[0][i] != current_file_size){ if(!silent) printf("\n"); current_file_size = report_array[0][i]; if(bif_flag) { bif_row++; bif_column=0; do_float(bif_fd,(double)(current_file_size),bif_row,bif_column++); } #ifdef NO_PRINT_LLD if(!silent) printf("%c%ld%c ",'"',(long)current_file_size,'"'); #else if(!silent) printf("%c%lld%c ",'"',(long long)current_file_size,'"'); #endif } if(bif_flag) do_float(bif_fd,(double)(report_array[who][i]),bif_row,bif_column++); #ifdef NO_PRINT_LLD if(!silent) printf(" %ld ",(long)report_array[who][i]); #else if(!silent) printf(" %lld ",(long long)report_array[who][i]); #endif } if(bif_flag) { bif_row++; bif_column=0; } if(!silent) printf("\n"); } /************************************************************************/ /* Wrapper that dumps each of the collected data sets. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void dump_excel(void) #else void dump_excel() #endif { if(bif_flag) { bif_fd=create_xls(bif_filename); do_label(bif_fd,command_line,bif_row++,bif_column); do_label(bif_fd," ",bif_row++,bif_column); do_label(bif_fd,"The top row is records sizes, the left column is file sizes",bif_row++,bif_column); } if(!silent) printf("Excel output is below:\n"); if ((!include_tflag) || (include_mask & (long long)WRITER_MASK)) { if(bif_flag) do_label(bif_fd,"Writer Report",bif_row++,bif_column); if(!silent) printf("\n%cWriter report%c\n",'"','"'); dump_report(2); if(bif_flag) do_label(bif_fd,"Re-writer Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-writer report%c\n",'"','"'); dump_report(3); } if ((!include_tflag) || (include_mask & (long long)READER_MASK)) { if(bif_flag) do_label(bif_fd,"Reader Report",bif_row++,bif_column); if(!silent) printf("\n%cReader report%c\n",'"','"'); dump_report(4); if(bif_flag) do_label(bif_fd,"Re-reader Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Reader report%c\n",'"','"'); dump_report(5); } if ((!include_tflag) || (include_mask & (long long)RANDOM_RW_MASK)) { if(bif_flag) do_label(bif_fd,"Random Read Report",bif_row++,bif_column); if(!silent) printf("\n%cRandom read report%c\n",'"','"'); dump_report(6); if(bif_flag) do_label(bif_fd,"Random Write Report",bif_row++,bif_column); if(!silent) printf("\n%cRandom write report%c\n",'"','"'); dump_report(7); } if ((!include_tflag) || (include_mask & (long long)REVERSE_MASK)) { if(bif_flag) do_label(bif_fd,"Backward Read Report",bif_row++,bif_column); if(!silent) printf("\n%cBackward read report%c\n",'"','"'); dump_report(8); } if ((!include_tflag) || (include_mask & (long long)REWRITE_REC_MASK)) { if(bif_flag) do_label(bif_fd,"Record Rewrite Report",bif_row++,bif_column); if(!silent) printf("\n%cRecord rewrite report%c\n",'"','"'); dump_report(9); } if ((!include_tflag) || (include_mask & (long long)STRIDE_READ_MASK)) { if(bif_flag) do_label(bif_fd,"Stride Read Report",bif_row++,bif_column); if(!silent) printf("\n%cStride read report%c\n",'"','"'); dump_report(10); } if ((!include_tflag) || (include_mask & (long long)FWRITER_MASK)) { if(bif_flag) do_label(bif_fd,"Fwrite Report",bif_row++,bif_column); if(!silent) printf("\n%cFwrite report%c\n",'"','"'); dump_report(11); if(bif_flag) do_label(bif_fd,"Re-fwrite Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Fwrite report%c\n",'"','"'); dump_report(12); } if ((!include_tflag) || (include_mask & (long long)FREADER_MASK)) { if(bif_flag) do_label(bif_fd,"Fread Report",bif_row++,bif_column); if(!silent) printf("\n%cFread report%c\n",'"','"'); dump_report(13); if(bif_flag) do_label(bif_fd,"Re-fread Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Fread report%c\n",'"','"'); dump_report(14); } #ifdef HAVE_PREAD if(Eflag) { if ((!include_tflag) || (include_mask & (long long)PWRITER_MASK)) { if(bif_flag) do_label(bif_fd,"Pwrite Report",bif_row++,bif_column); if(!silent) printf("\n%cPwrite report%c\n",'"','"'); dump_report(15); if(bif_flag) do_label(bif_fd,"Re-pwrite Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Pwrite report%c\n",'"','"'); dump_report(16); } if ((!include_tflag) || (include_mask & (long long)PREADER_MASK)) { if(bif_flag) do_label(bif_fd,"Pread Report",bif_row++,bif_column); if(!silent) printf("\n%cPread report%c\n",'"','"'); dump_report(17); if(bif_flag) do_label(bif_fd,"Re-pread Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Pread report%c\n",'"','"'); dump_report(18); } #ifdef HAVE_PREADV if ((!include_tflag) || (include_mask & (long long)PWRITEV_MASK)) { if(bif_flag) do_label(bif_fd,"Pwritev Report",bif_row++,bif_column); if(!silent) printf("\n%cPwritev report%c\n",'"','"'); dump_report(19); if(bif_flag) do_label(bif_fd,"Re-pwritev Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Pwritev report%c\n",'"','"'); dump_report(20); } if ((!include_tflag) || (include_mask & (long long)PREADV_MASK)) { if(bif_flag) do_label(bif_fd,"Preadv Report",bif_row++,bif_column); if(!silent) printf("\n%cPreadv report%c\n",'"','"'); dump_report(21); if(bif_flag) do_label(bif_fd,"Re-preadv Report",bif_row++,bif_column); if(!silent) printf("\n%cRe-Preadv report%c\n",'"','"'); dump_report(22); } #endif } #endif if (cpuutilflag) dump_cputimes(); if(bif_flag) close_xls(bif_fd); } /************************************************************************/ /* dump_times() */ /* Dumps the Excel CPU times report to stdout and to the bif file. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void dump_times(long long who) #else dump_times(who) long long who; #endif { long long i; off64_t current_file_size; off64_t rec_size; if (bif_flag) bif_column++; if(!silent) printf(" "); for (rec_size = get_next_record_size(0); rec_size <= orig_max_rec_size; rec_size = get_next_record_size(rec_size)) { if (rec_size == 0) break; if (bif_flag) do_float(bif_fd, (double)(rec_size/1024), bif_row, bif_column++); #ifdef NO_PRINT_LLD if(!silent) printf(" %c%ld%c",'"',(long)(rec_size/1024),'"'); #else if(!silent) printf(" %c%lld%c",'"',(long long)(rec_size/1024),'"'); #endif } if(!silent) printf("\n"); if (bif_flag) { bif_column=0; bif_row++; } current_file_size = report_array[0][0]; if (bif_flag) { do_float(bif_fd, (double)(current_file_size), bif_row, bif_column++); } #ifdef NO_PRINT_LLD if(!silent) printf("%c%ld%c ",'"',(long)current_file_size,'"'); #else if(!silent) printf("%c%lld%c ",'"',(long long)current_file_size,'"'); #endif for (i = 0; i <= max_y; i++) { if (report_array[0][i] != current_file_size) { if(!silent) printf("\n"); current_file_size = report_array[0][i]; if (bif_flag) { bif_row++; bif_column=0; do_float(bif_fd, (double)(current_file_size), bif_row, bif_column++); } #ifdef NO_PRINT_LLD if(!silent) printf("%c%ld%c ",'"',(long)current_file_size,'"'); #else if(!silent) printf("%c%lld%c ",'"',(long long)current_file_size,'"'); #endif } if (bif_flag) do_float(bif_fd, (double)(runtimes [who][i].cpuutil), bif_row, bif_column++); if(!silent) printf(" %6.2f", runtimes [who][i].cpuutil); } if(!silent) printf("\n"); if (bif_flag) { bif_row++; bif_column=0; } } /************************************************************************/ /* Wrapper that dumps each of the collected data sets. */ /* This one dumps only the collected CPU times. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void dump_cputimes(void) #else void dump_cputimes(void) #endif { bif_row++; bif_column = 0; if ((!include_tflag) || (include_mask & (long long)WRITER_MASK)) { if(bif_flag) do_label(bif_fd, "Writer CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cWriter CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(2); if(bif_flag) do_label(bif_fd, "Re-writer CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-writer CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(3); } if ((!include_tflag) || (include_mask & (long long)READER_MASK)) { if(bif_flag) do_label(bif_fd, "Reader CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cReader CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(4); if(bif_flag) do_label(bif_fd, "Re-reader CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Reader CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(5); } if ((!include_tflag) || (include_mask & (long long)RANDOM_RW_MASK)) { if(bif_flag) do_label(bif_fd, "Random Read CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRandom read CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(6); if(bif_flag) do_label(bif_fd, "Random Write CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRandom write CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(7); } if ((!include_tflag) || (include_mask & (long long)REVERSE_MASK)) { if(bif_flag) do_label(bif_fd, "Backward Read CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cBackward read CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(8); } if ((!include_tflag) || (include_mask & (long long)REWRITE_REC_MASK)) { if(bif_flag) do_label(bif_fd, "Record Rewrite CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRecord rewrite CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(9); } if ((!include_tflag) || (include_mask & (long long)STRIDE_READ_MASK)) { if(bif_flag) do_label(bif_fd, "Stride Read CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cStride read CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(10); } if ((!include_tflag) || (include_mask & (long long)FWRITER_MASK)) { if(bif_flag) do_label(bif_fd, "Fwrite CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cFwrite CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(11); if(bif_flag) do_label(bif_fd, "Re-fwrite CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Fwrite CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(12); } if ((!include_tflag) || (include_mask & (long long)FREADER_MASK)) { if(bif_flag) do_label(bif_fd, "Fread CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cFread CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(13); if(bif_flag) do_label(bif_fd, "Re-fread CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Fread CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(14); } #ifdef HAVE_PREAD if(Eflag) { if ((!include_tflag) || (include_mask & (long long)PWRITER_MASK)) { if(bif_flag) do_label(bif_fd, "Pwrite CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cPwrite CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(15); if(bif_flag) do_label(bif_fd, "Re-pwrite CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Pwrite CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(16); } if ((!include_tflag) || (include_mask & (long long)PREADER_MASK)) { if(bif_flag) do_label(bif_fd, "Pread CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cPread CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(17); if(bif_flag) do_label(bif_fd, "Re-pread CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Pread CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(18); } #ifdef HAVE_PREADV if ((!include_tflag) || (include_mask & (long long)PWRITEV_MASK)) { if(bif_flag) do_label(bif_fd, "Pwritev CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cPwritev CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(19); if(bif_flag) do_label(bif_fd, "Re-pwritev CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Pwritev CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(20); } if ((!include_tflag) || (include_mask & (long long)PREADV_MASK)) { if(bif_flag) do_label(bif_fd, "Preadv CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cPreadv CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(21); if(bif_flag) do_label(bif_fd, "Re-preadv CPU utilization report (Zero values should be ignored)", bif_row++, bif_column); if(!silent) printf("\n%cRe-Preadv CPU utilization report (Zero values should be ignored)%c\n",'"','"'); dump_times(22); } #endif } #endif } /************************************************************************/ /* Internal memory allocation mechanism. Uses shared memory or mmap */ /************************************************************************/ #ifdef HAVE_ANSIC_C char * alloc_mem(long long size, int shared_flag) #else char * alloc_mem(size,shared_flag) long long size; int shared_flag; #endif { long long size1; char *addr,*dumb; #ifdef SHARED_MEM int shmid; #endif int tfd; long long tmp; #if defined(solaris) char mmapFileName[]="mmap_tmp_XXXXXX"; #endif tmp = 0; dumb = (char *)0; tfd=0; size1=l_max(size,page_size); if(!distributed) { if(!trflag) { addr=(char *)malloc((size_t)size1); return(addr); } if(use_thread) { addr=(char *)malloc((size_t)size1); return(addr); } } if(!shared_flag) { addr=(char *)malloc((size_t)size1); return(addr); } #ifdef SHARED_MEM size1=l_max(size,page_size); size1=(size1 +page_size) & ~(page_size-1); shmid=(int)shmget((key_t)(IPC_PRIVATE), (size_t)size1 , (int)(IPC_CREAT|0666)); if(shmid < (int)0) { printf("\nUnable to get shared memory segment(shmget)\n"); #ifdef NO_PRINT_LLD printf("shmid = %d, size = %ld, size1 = %lu, Error %d\n",shmid,(long)size,(size_t)size1,errno); #else printf("shmid = %d, size = %lld, size1 = %lu, Error %d\n",shmid,(long long)size,(unsigned long)size1,errno); #endif exit(119); } /*addr = (char *)shmat(shmid, 0, SHM_W);*/ /* Some systems will not take the above but * will default to read/write if no flags * are provided. (AIX) * The POSIX standard states that if SHM_RDONLY * is not specified then it will be read/write. */ addr = (char *)shmat((int)shmid, 0, 0); #ifdef _64BIT_ARCH_ if((long long)addr == (long long)-1) #else if((long)addr == (long)-1) #endif { printf("\nUnable to get shared memory segment\n"); printf("..Error %d\n",errno); exit(120); } shmctl(shmid, IPC_RMID, 0); return(addr); #else size1=l_max(size,page_size); size1=(size1 +page_size) & ~(page_size-1); #if defined(bsd4_2) && !defined(IOZ_macosx) if((tfd = creat("mmap.tmp", 0666))<0) { printf("Unable to create tmp file\n"); exit(121); } addr=(char *)mmap(0,&size1,PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, tfd, 0); unlink("mmap.tmp"); #else #if defined(solaris) tfd=mkstemp(mmapFileName); if(tfd < 0) { printf("Unable to create tmp file\n"); exit(121); } dumb=(char *)malloc((size_t)size1); bzero(dumb,size1); write(tfd,dumb,size1); free(dumb); addr=(char *)mmap(0,(size_t)size1,PROT_WRITE|PROT_READ, MAP_SHARED, tfd, 0); unlink(mmapFileName); #else #if defined(SCO) || defined(SCO_Unixware_gcc) || defined(Windows) char mmapFileName[]="mmap_tmp_XXXXXX"; tfd=mkstemp(mmapFileName); if(tfd < 0) { printf("Unable to create tmp file\n"); exit(121); } dumb=(char *)malloc((size_t)size1); bzero(dumb,size1); write(tfd,dumb,size1); free(dumb); addr=(char *)mmap(0,(size_t)size1,PROT_WRITE|PROT_READ, MAP_SHARED, tfd, 0); unlink(mmapFileName); #else addr=(char *)mmap(0,(size_t)size1,PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_SHARED, -1, 0); #endif #endif #endif if((char *)addr == (char *)-1) { printf("\nUnable to get memory segment\n"); printf("Error %d\n",errno); exit(122); } if(debug1) printf("Got shared memory for size %lld\n",size1); return(addr); #endif } /************************************************************************/ /* Implementation of poll() function. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void Poll(long long time1) #else void Poll(time1) long long time1; #endif { struct timeval howlong; howlong.tv_sec=(int)(time1/100000); howlong.tv_usec=(int)(time1%100000); /* Get into u.s. */ select(0, 0, 0, 0, &howlong); } /************************************************************************/ /* Implementation of max() function. */ /************************************************************************/ #ifdef HAVE_ANSIC_C long long l_max(long long one,long long two) #else long long l_max(one,two) long long one,two; #endif { if(one > two) return(one); else return(two); } /************************************************************************/ /* Internal Kill. With stonewalling disabled, kill does nothing */ /************************************************************************/ #ifdef HAVE_ANSIC_C void Kill(long long pid,long long sig) #else void Kill(pid,sig) long long pid,sig; #endif { if(!xflag) { /*printf("Killing %d\n",pid);*/ kill((pid_t)pid,(int)sig); } } /************************************************************************/ /* Implementation of min() function. */ /************************************************************************/ #ifdef HAVE_ANSIC_C long long l_min(long long num1,long long num2) #else long long l_min(num1,num2) long long num1,num2; #endif { if(num1 >= num2) return num2; else return num1; } /************************************************************************/ /* Routine to call throughput tests many times. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void multi_throughput_test(long long mint,long long maxt) #else void multi_throughput_test(mint, maxt) long long mint, maxt; #endif { int *t_rangeptr, *t_rangecurs; int *saveptr = (int *)0; int tofree = 0; long long i; if(t_count == 0){ t_count = (int) maxt - mint + 1; t_rangeptr = (int *) malloc((size_t)sizeof(int)*t_count); saveptr = t_rangeptr; tofree = 1; t_rangecurs = t_rangeptr; for(i=mint; i<= maxt; i++) { *(t_rangecurs++) = i; } } else { t_rangeptr = &t_range[0]; } for(i=0; i < t_count; i++){ num_child = *(t_rangeptr++); current_client_number=0; /* Need to start with 1 */ throughput_test(); current_x=0; current_y++; } if(Rflag) dump_throughput(); if(tofree) free(saveptr); } /************************************************************************/ /* Routine to purge the buffer cache by unmounting drive. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void purge_buffer_cache() #else purge_buffer_cache() #endif { char command[1024]; int ret,i; strcpy(command,"umount "); strcat(command, mountname); /* umount might fail if the device is still busy, so retry unmounting several times with increasing delays */ for (i = 1; i < 200; ++i) { ret = system(command); if (ret == 0) break; sleep(i); /* seconds */ } strcpy(command,"mount "); strcat(command, mountname); /* mount might fail if the device is still busy, so retry mounting several times with increasing delays */ for (i = 1; i < 10; ++i) { ret = system(command); if (ret == 0) break; sleep(i); /* seconds */ } } /************************************************************************/ /* Thread write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_write_test(int x) #else void * thread_write_test( x) #endif { struct child_stats *child_stat; double starttime1 = 0; double temp_time; double walltime, cputime; double compute_val = (double)0; float delay = (float)0; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; off64_t traj_offset; off64_t lock_offset=0; off64_t save_offset=0; long long flags,traj_size; long long w_traj_bytes_completed; long long w_traj_ops_completed; FILE *w_traj_fd; int fd; long long recs_per_buffer; long long stopped,i; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long xx,xx2; char *dummyfile [MAXSTREAMS]; /* name of dummy file */ char *nbuff; char *maddr; char *wmaddr,*free_addr; char now_string[30]; int anwser,bind_cpu,wval; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif off64_t filebytes64; char tmpname[256]; FILE *thread_wqfd; FILE *thread_Lwqfd; #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif double burst_acc_time_sec = 0; if(compute_flag) delay=compute_time; nbuff=maddr=wmaddr=free_addr=0; hist_time=thread_qtime_stop=thread_qtime_start=0; thread_wqfd=w_traj_fd=thread_Lwqfd=(FILE *)0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; if(w_traj_flag) { filebytes64 = w_traj_fsize; numrecs64=w_traj_ops; } else { filebytes64 = numrecs64*reclen; } written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; w_traj_bytes_completed=w_traj_ops_completed=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(use_thread) { xx = (long long)((long)x); } else { xx=chid; } #endif #ifndef NO_THREADS #if defined(_HPUX_SOURCE) || defined(linux) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1 ) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } /*****************/ /* Children only */ /*******************************************************************/ /* Initial write throughput performance test. **********************/ /*******************************************************************/ #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_ALWAYS,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); CloseHandle(hand); } #endif if(oflag) flags=O_RDWR|O_SYNC|O_CREAT; else flags=O_RDWR|O_CREAT; if(del_flag && mix_test) flags |= O_TRUNC; #if defined(O_DSYNC) if(odsync) flags |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); } else { #endif if((fd = I_OPEN(dummyfile[xx], (int)flags,0640))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("\nCan not open temp file: %s\n", dummyfile[xx]); perror("open"); exit(125); } #if defined(Windows) } #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif if(mmapflag) { maddr=(char *)initfile(fd,(filebytes64),1,PROT_READ|PROT_WRITE); } if(reclen < cache_size ) { recs_per_buffer = cache_size/reclen ; nbuff=&nbuff[(xx%recs_per_buffer)*reclen]; } if(fetchon) /* Prefetch into processor cache */ fetchit(nbuff,reclen); if((verify && !no_copy_flag) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); if(w_traj_flag) w_traj_fd=open_w_traj(); child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag=CHILD_STATE_READY; /* Tell parent child is ready to go */ if(distributed && client_iozone) tell_master_ready(chid); if(distributed && client_iozone) { if(cdebug) { fprintf(newstdout,"Child %d waiting for go from master\n",(int)xx); fflush(newstdout); } wait_for_master_go(chid); if(cdebug) { fprintf(newstdout,"Child %d received go from master\n",(int)xx); fflush(newstdout); } } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } written_so_far=0; child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->actual = 0; child_stat->throughput = 0; stopped=0; if(file_lock) if(mylockf((int) fd, (int) 1, (int)0) != 0) printf("File lock for write failed. %d\n",errno); if(Q_flag) { sprintf(tmpname,"Child_%d_wol.dat",(int)xx); thread_wqfd=fopen(tmpname,"a"); if(thread_wqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_wqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Write test start: ",now_string); } starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(w_traj_flag) rewind(w_traj_fd); for(i=0; ithroughput = (time_so_far() - starttime1)-time_res - burst_acc_time_sec; if(include_close) { if((fd = I_OPEN(dummyfile[xx], (int)flags,0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("\nCan not open temp file: %s\n", dummyfile[xx]); perror("open"); exit(125); } I_LSEEK(fd,save_offset,SEEK_SET); } if(child_stat->throughput < (double).000001) { child_stat->throughput = time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; if(debug1) { printf("\n(%ld) Stopped by another\n", (long)xx); } stopped=1; } if(purge) purgeit(nbuff,reclen); if(Q_flag || hist_summary || op_rate_flag) { thread_qtime_start=time_so_far(); } again: if(mmapflag) { wmaddr = &maddr[i*reclen]; fill_area((long long*)nbuff,(long long*)wmaddr,(long long)reclen); /*printf("CHid: %lld Writing offset %lld for length of %lld\n",chid,i*reclen,reclen);*/ if(!mmapnsflag) { if(mmapasflag) msync(wmaddr,(size_t)reclen,MS_ASYNC); if(mmapssflag) msync(wmaddr,(size_t)reclen,MS_SYNC); } } else { if(async_flag) { if(no_copy_flag) { free_addr=nbuff=(char *)malloc((size_t)reclen+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,i); async_write_no_copy(gc, (long long)fd, nbuff, reclen, (i*reclen), depth,free_addr); } else async_write(gc, (long long)fd, nbuff, reclen, (i*reclen), depth); } else { #if defined(Windows) if(unbuffered) { WriteFile(hand,nbuff,reclen, (LPDWORD)&wval,0); } else { #endif wval=write(fd, nbuff, (size_t) reclen); #ifndef NO_THREADS count_burst(&burst_acc_time_sec, xx); #endif #if defined(Windows) } #endif if(wval != reclen) { if(*stop_flag && !stopped){ if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } temp_time = time_so_far(); child_stat->throughput = (temp_time - starttime1)-time_res - burst_acc_time_sec; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; if(debug1) { printf("\n(%ld) Stopped by another\n", (long)xx); } stopped=1; goto again; } /* Note: Writer must finish even though told to stop. Otherwise the readers will fail. The code will capture bytes transfered before told to stop but let the writer complete. */ #ifdef NO_PRINT_LLD printf("\nError writing block %ld, fd= %d\n", (long)i, fd); #else printf("\nError writing block %lld, fd= %d\n", (long long)i, fd); #endif if(wval==-1) perror("write"); if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(127); } } } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long)((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_wqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_wqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } w_traj_ops_completed++; w_traj_bytes_completed+=reclen; written_so_far+=reclen/1024; if(*stop_flag) { written_so_far-=reclen/1024; w_traj_bytes_completed-=reclen; } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)0)) printf("Write unlock failed. %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } if(include_close) { if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } if(!stopped){ temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec); else child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; } if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid, child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_WRITE_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); if (debug1) { #ifdef NO_PRINT_LLD printf(" child/slot: %ld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n", (long)xx, #else printf(" child/slot: %lld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n", (long long)xx, #endif walltime, cputime, cpu_util(cputime, walltime)); } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ stopped=0; /*******************************************************************/ /* End write performance test. *************************************/ /*******************************************************************/ if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(!include_close) { if(mmapflag) { msync(maddr,(size_t)numrecs64*reclen,MS_SYNC); /*Clean up before read starts running*/ mmap_end(maddr,(unsigned long long)numrecs64*reclen); }else fsync(fd); #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } if(Q_flag && (thread_wqfd !=0) ) fclose(thread_wqfd); free(dummyfile[xx]); if(w_traj_flag) fclose(w_traj_fd); if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Write test finished: ",now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("write",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } #ifdef HAVE_PREAD /************************************************************************/ /* Thread pwrite test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_pwrite_test(int x) #else void * thread_pwrite_test( x) #endif { struct child_stats *child_stat; double starttime1 = 0; double temp_time; double walltime, cputime; double compute_val = (double)0; float delay = (float)0; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; off64_t traj_offset; off64_t lock_offset=0; long long flags,traj_size; long long w_traj_bytes_completed; long long w_traj_ops_completed; FILE *w_traj_fd; int fd; long long recs_per_buffer; long long stopped,i; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long xx,xx2; char *dummyfile [MAXSTREAMS]; /* name of dummy file */ char *nbuff; char *maddr; char *wmaddr,*free_addr; char now_string[30]; int anwser,bind_cpu,wval; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif off64_t filebytes64; char tmpname[256]; FILE *thread_wqfd; FILE *thread_Lwqfd; #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif if(compute_flag) delay=compute_time; nbuff=maddr=wmaddr=free_addr=0; hist_time=thread_qtime_stop=thread_qtime_start=0; thread_wqfd=w_traj_fd=thread_Lwqfd=(FILE *)0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; if(w_traj_flag) { filebytes64 = w_traj_fsize; numrecs64=w_traj_ops; } else { filebytes64 = numrecs64*reclen; } written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; w_traj_bytes_completed=w_traj_ops_completed=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(use_thread) { xx = (long long)((long)x); } else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined( _HPUX_SOURCE ) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1 ) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } /*****************/ /* Children only */ /*******************************************************************/ /* Initial pwrite throughput performance test. *********************/ /*******************************************************************/ if(!notruncate) { if((fd = I_CREAT(dummyfile[xx], 0640))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(123); } close(fd); } if(oflag) flags=O_RDWR|O_SYNC|O_CREAT; else flags=O_RDWR|O_CREAT; #if defined(O_DSYNC) if(odsync) flags |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif if((fd = I_OPEN(dummyfile[xx], (int)flags,0640))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("\nCan not open temp file: %s\n", dummyfile[xx]); perror("open"); exit(125); } #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif if(mmapflag) { maddr=(char *)initfile(fd,(filebytes64),1,PROT_READ|PROT_WRITE); } if(reclen < cache_size ) { recs_per_buffer = cache_size/reclen ; nbuff=&nbuff[(xx%recs_per_buffer)*reclen]; } if(fetchon) /* Prefetch into processor cache */ fetchit(nbuff,reclen); if((verify && !no_copy_flag) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); if(w_traj_flag) w_traj_fd=open_w_traj(); child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag=CHILD_STATE_READY; /* Tell parent child is ready to go */ if(distributed && client_iozone) tell_master_ready(chid); if(distributed && client_iozone) { if(cdebug) { fprintf(newstdout,"Child %d waiting for go from master\n",(int)xx); fflush(newstdout); } wait_for_master_go(chid); if(cdebug) { fprintf(newstdout,"Child %d received go from master\n",(int)xx); fflush(newstdout); } } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } written_so_far=0; child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->actual = 0; child_stat->throughput = 0; stopped=0; if(file_lock) if(mylockf((int) fd, (int) 1, (int)0) != 0) printf("File lock for write failed. %d\n",errno); if(Q_flag) { sprintf(tmpname,"Child_%d_pwol.dat",(int)xx); thread_wqfd=fopen(tmpname,"a"); if(thread_wqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_wqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Pwrite test start: ",now_string); } starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(w_traj_flag) rewind(w_traj_fd); for(i=0; ithroughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput = time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; if(debug1) { printf("\n(%ld) Stopped by another\n", (long)xx); } stopped=1; } if(purge) purgeit(nbuff,reclen); if(Q_flag || hist_summary || op_rate_flag) { thread_qtime_start=time_so_far(); } again: if(mmapflag) { wmaddr = &maddr[traj_offset]; fill_area((long long*)nbuff,(long long*)wmaddr,(long long)reclen); /*printf("CHid: %lld Writing offset %lld for length of %lld\n",chid,i*reclen,reclen);*/ if(!mmapnsflag) { if(mmapasflag) msync(wmaddr,(size_t)reclen,MS_ASYNC); if(mmapssflag) msync(wmaddr,(size_t)reclen,MS_SYNC); } } else { if(async_flag) { if(no_copy_flag) { free_addr=nbuff=(char *)malloc((size_t)reclen+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,i); async_write_no_copy(gc, (long long)fd, nbuff, reclen, (traj_offset), depth,free_addr); } else async_write(gc, (long long)fd, nbuff, reclen, (traj_offset), depth); } else { wval=I_PWRITE(fd, nbuff, reclen, traj_offset); if(wval != reclen) { if(*stop_flag && !stopped){ if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } temp_time = time_so_far(); child_stat->throughput = (temp_time - starttime1)-time_res; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; if(debug1) { printf("\n(%ld) Stopped by another\n", (long)xx); } stopped=1; goto again; } /* Note: Writer must finish even though told to stop. Otherwise the readers will fail. The code will capture bytes transfered before told to stop but let the writer complete. */ #ifdef NO_PRINT_LLD printf("\nError pwriting block %ld, fd= %d\n", (long)i, fd); #else printf("\nError pwriting block %lld, fd= %d\n", (long long)i, fd); #endif if(wval==-1) perror("pwrite"); if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(127); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_wqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_wqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } w_traj_ops_completed++; w_traj_bytes_completed+=reclen; written_so_far+=reclen/1024; if(*stop_flag) { written_so_far-=reclen/1024; w_traj_bytes_completed-=reclen; } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)0)) printf("Write unlock failed. %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } if(include_close) { if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); close(fd); } if(!stopped){ temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; } if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid, child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_PWRITE_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); if (debug1) { #ifdef NO_PRINT_LLD printf(" child/slot: %ld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n",(long)xx, #else printf(" child/slot: %lld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n",(long long)xx, #endif walltime, cputime, cpu_util(cputime, walltime)); } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ stopped=0; /*******************************************************************/ /* End pwrite performance test. *************************************/ /*******************************************************************/ if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(!include_close) { if(mmapflag) { msync(maddr,(size_t)numrecs64*reclen,MS_SYNC); /*Clean up before read starts running*/ mmap_end(maddr,(unsigned long long)numrecs64*reclen); }else fsync(fd); close(fd); } if(Q_flag && (thread_wqfd !=0) ) fclose(thread_wqfd); free(dummyfile[xx]); if(w_traj_flag) fclose(w_traj_fd); if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Pwrite test finished: ",now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Pwrite",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } #endif /************************************************************************/ /* Thread re-write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_rwrite_test(int x) #else void * thread_rwrite_test(x) #endif { /************************/ /* Children only here */ /************************/ struct child_stats *child_stat; long long xx,xx2; double compute_val = (double)0; double walltime, cputime; float delay = (float)0; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; off64_t traj_offset; off64_t lock_offset=0; long long w_traj_bytes_completed; long long w_traj_ops_completed; int fd; FILE *w_traj_fd; long long flags = 0; double starttime1 = 0; double temp_time; long long recs_per_buffer,traj_size; long long i; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far=0; char *dummyfile [MAXSTREAMS]; /* name of dummy file */ char *nbuff; char *maddr,*free_addr; char *wmaddr; char now_string[30]; int anwser,bind_cpu,wval; FILE *thread_rwqfd,*thread_Lwqfd; char tmpname[256]; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif double burst_acc_time_sec = 0; if(compute_flag) delay=compute_time; wmaddr=nbuff=maddr=free_addr=0; thread_rwqfd=w_traj_fd=thread_Lwqfd=(FILE *)0; hist_time=traj_offset=thread_qtime_stop=thread_qtime_start=0; walltime=cputime=0; anwser=bind_cpu=0; w_traj_bytes_completed=w_traj_ops_completed=0; written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; if(w_traj_flag) { filebytes64 = w_traj_fsize; numrecs64=w_traj_ops; } else { filebytes64 = numrecs64*reclen; } #ifdef NO_THREADS xx=chid; #else if(use_thread) xx=(long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined( _HPUX_SOURCE ) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } flags = O_RDWR; if(oflag) flags|= O_SYNC; #if defined(O_DSYNC) if(odsync) flags|= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_ALWAYS,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); } else { #endif if((fd = I_OPEN(dummyfile[xx], (int)flags,0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); #ifdef NO_PRINT_LLD printf("\nChild %ld\n",(long)xx); #else printf("\nChild %lld\n",(long long)xx); #endif child_stat->flag = CHILD_STATE_HOLD; perror(dummyfile[xx]); exit(128); } #if defined(Windows) } #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif if(mmapflag) { maddr=(char *)initfile(fd,(numrecs64*reclen),1,PROT_READ|PROT_WRITE); } if(fetchon) fetchit(nbuff,reclen); if(w_traj_flag) w_traj_fd=open_w_traj(); if(Q_flag) { sprintf(tmpname,"Child_%d_rwol.dat",(int)xx); thread_rwqfd=fopen(tmpname,"a"); if(thread_rwqfd==0) { printf("Unable to open %s\n",tmpname); client_error=errno; if(distributed && client_iozone) send_stop(); exit(40); } fprintf(thread_rwqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Rewrite test start: ",now_string); } child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) tell_master_ready(chid); if(distributed && client_iozone) { if(cdebug) { fprintf(newstdout,"Child %d waiting for go from master\n",(int)xx); fflush(newstdout); } wait_for_master_go(chid); if(cdebug) { fprintf(newstdout,"Child %d received go from master\n",(int)xx); fflush(newstdout); } } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(file_lock) if(mylockf((int) fd, (int) 1, (int)0) != 0) printf("File lock for write failed. %d\n",errno); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(w_traj_flag) rewind(w_traj_fd); if((verify && !no_copy_flag) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); for(i=0; iflag = CHILD_STATE_HOLD; signal_handler(); } } } re_written_so_far+=reclen/1024; w_traj_ops_completed++; w_traj_bytes_completed+=reclen; if(*stop_flag) { re_written_so_far-=reclen/1024; w_traj_bytes_completed-=reclen; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rwqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_rwqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)0)) printf("Write unlock failed. %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } temp_time=time_so_far(); child_stat=(struct child_stats *)&shmaddr[xx]; if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec); else child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*re_written_so_far=(re_written_so_far*1024)/reclen;*/ re_written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)re_written_so_far/child_stat->throughput; child_stat->actual = (double)re_written_so_far; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid, child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_REWRITE_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); mmap_end(maddr,(unsigned long long)filebytes64); } else fsync(fd); #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } free(dummyfile[xx]); if(Q_flag && (thread_rwqfd !=0) ) fclose(thread_rwqfd); if(w_traj_flag) fclose(w_traj_fd); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild Stopping %ld\n",(long)xx); #else printf("\nChild Stopping %lld\n",(long long)xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Rewrite test finished: ",now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Rewrite",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* Thread read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_read_test(int x) #else void * thread_read_test(x) #endif { long long xx,xx2; struct child_stats *child_stat; double walltime, cputime; long long r_traj_bytes_completed; long long r_traj_ops_completed; int fd; FILE *r_traj_fd,*thread_rqfd; FILE *thread_Lwqfd; long long flags = 0; off64_t traj_offset; off64_t lock_offset=0; double starttime1 = 0; float delay = 0; double temp_time; double thread_qtime_start,thread_qtime_stop; double hist_time; double desired_op_rate_time; double actual_rate; double compute_val = (double)0; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long recs_per_buffer,traj_size; off64_t i; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ char *nbuff=0; char *maddr=0; char *wmaddr=0; char tmpname[256]; volatile char *buffer1; char now_string[30]; int anwser,bind_cpu; long wval; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif if(compute_flag) delay=compute_time; thread_rqfd=thread_Lwqfd=r_traj_fd=(FILE *)0; hist_time=traj_offset=thread_qtime_stop=thread_qtime_start=0; walltime=cputime=0; anwser=bind_cpu=0; r_traj_bytes_completed=r_traj_ops_completed=0; written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; if(r_traj_flag) { filebytes64 = r_traj_fsize; numrecs64=r_traj_ops; } else { filebytes64 = numrecs64*reclen; } #ifdef NO_THREADS xx=chid; #else if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } if(oflag) flags=O_RDONLY|O_SYNC; else flags=O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); SetFilePointer(hand,(LONG)0,0,FILE_BEGIN); } else { #endif if((fd = I_OPEN(dummyfile[xx], (int)flags,0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(130); } #if defined(Windows) } #endif #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,(numrecs64*reclen),0,PROT_READ); } child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } /*****************/ /* Children only */ /*****************/ if(Q_flag) { sprintf(tmpname,"Child_%d_rol.dat",(int)xx); thread_rqfd=fopen(tmpname,"a"); if(thread_rqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_rqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Read test start: ",now_string); } if(r_traj_flag) r_traj_fd=open_r_traj(); if(fetchon) fetchit(nbuff,reclen); child_stat=(struct child_stats *)&shmaddr[xx]; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else { /* Wait for signal from parent */ while(child_stat->flag!=CHILD_STATE_BEGIN) Poll((long long)1); } if(file_lock) if(mylockf((int) fd, (int) 1, (int)1) != 0) printf("File lock for read failed. %d\n",errno); starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(r_traj_flag) rewind(r_traj_fd); for(i=0; iflag = CHILD_STATE_HOLD; exit(132); } } } if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(133); } } else { if(verify_buffer(nbuff,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(134); } } } if(async_flag && no_copy_flag) async_release(gc); read_so_far+=reclen/1024; r_traj_bytes_completed+=reclen; r_traj_ops_completed++; if(*stop_flag) { read_so_far-=reclen/1024; r_traj_bytes_completed-=reclen; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_rqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)1)) printf("Read unlock failed. %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } temp_time = time_so_far(); child_stat=(struct child_stats *)&shmaddr[xx]; if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*read_so_far=(read_so_far*1024)/reclen;*/ read_so_far=r_traj_ops_completed; } child_stat->throughput = read_so_far/child_stat->throughput; child_stat->actual = read_so_far; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_READ_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ /*fsync(fd);*/ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); mmap_end(maddr,(unsigned long long)filebytes64); }else fsync(fd); #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } if(Q_flag && (thread_rqfd !=0) ) fclose(thread_rqfd); free(dummyfile[xx]); if(r_traj_flag) fclose(r_traj_fd); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Read test finished: ",now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Read",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } #ifdef HAVE_PREAD /************************************************************************/ /* Thread pread test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_pread_test(int x) #else void * thread_pread_test(x) #endif { long long xx,xx2; struct child_stats *child_stat; double walltime, cputime; long long r_traj_bytes_completed; long long r_traj_ops_completed; int fd; FILE *r_traj_fd,*thread_rqfd; FILE *thread_Lwqfd; long long flags = 0; off64_t traj_offset; off64_t lock_offset=0; double starttime1 = 0; float delay = 0; double temp_time; double thread_qtime_start,thread_qtime_stop; double hist_time; double desired_op_rate_time; double actual_rate; double compute_val = (double)0; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long recs_per_buffer,traj_size; off64_t i; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ char *nbuff=0; char *maddr=0; char *wmaddr=0; char tmpname[256]; char now_string[30]; volatile char *buffer1; int anwser,bind_cpu; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif if(compute_flag) delay=compute_time; thread_rqfd=thread_Lwqfd=r_traj_fd=(FILE *)0; hist_time=traj_offset=thread_qtime_stop=thread_qtime_start=0; walltime=cputime=0; anwser=bind_cpu=0; r_traj_bytes_completed=r_traj_ops_completed=0; written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; if(r_traj_flag) { filebytes64 = r_traj_fsize; numrecs64=r_traj_ops; } else { filebytes64 = numrecs64*reclen; } #ifdef NO_THREADS xx=chid; #else if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #ifdef _HPUX_SOURCE if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } if(oflag) flags=O_RDONLY|O_SYNC; else flags=O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif if((fd = I_OPEN(dummyfile[xx], (int)flags,0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(130); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,(numrecs64*reclen),0,PROT_READ); } child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } /*****************/ /* Children only */ /*****************/ if(Q_flag) { sprintf(tmpname,"Child_%d_prol.dat",(int)xx); thread_rqfd=fopen(tmpname,"a"); if(thread_rqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_rqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Pread test start: ",now_string); } if(r_traj_flag) r_traj_fd=open_r_traj(); if(fetchon) fetchit(nbuff,reclen); child_stat=(struct child_stats *)&shmaddr[xx]; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else { /* Wait for signal from parent */ while(child_stat->flag!=CHILD_STATE_BEGIN) Poll((long long)1); } if(file_lock) if(mylockf((int) fd, (int) 1, (int)1) != 0) printf("File lock for read failed. %d\n",errno); starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(r_traj_flag) rewind(r_traj_fd); for(i=0; iflag = CHILD_STATE_HOLD; exit(132); } } } if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(133); } } else { if(verify_buffer(nbuff,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(134); } } } if(async_flag && no_copy_flag) async_release(gc); read_so_far+=reclen/1024; r_traj_bytes_completed+=reclen; r_traj_ops_completed++; if(*stop_flag) { read_so_far-=reclen/1024; r_traj_bytes_completed-=reclen; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_rqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)1)) printf("Read unlock failed. %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } close(fd); } temp_time = time_so_far(); child_stat=(struct child_stats *)&shmaddr[xx]; if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*read_so_far=(read_so_far*1024)/reclen;*/ read_so_far=r_traj_ops_completed; } child_stat->throughput = read_so_far/child_stat->throughput; child_stat->actual = read_so_far; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_READ_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ /*fsync(fd);*/ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); mmap_end(maddr,(unsigned long long)filebytes64); }else fsync(fd); close(fd); } if(Q_flag && (thread_rqfd !=0) ) fclose(thread_rqfd); free(dummyfile[xx]); if(r_traj_flag) fclose(r_traj_fd); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Pread test finished: ", now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Pread",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } #endif /************************************************************************/ /* Thread re-read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_rread_test(int x) #else void * thread_rread_test(x) #endif { long long xx,xx2; char *nbuff; struct child_stats *child_stat; int fd; FILE *r_traj_fd,*thread_rrqfd; FILE *thread_Lwqfd; long long r_traj_bytes_completed; double walltime, cputime; long long r_traj_ops_completed; off64_t traj_offset; off64_t lock_offset=0; long long flags = 0; double starttime1 = 0; float delay = 0; double temp_time; double thread_qtime_start,thread_qtime_stop; double hist_time; double desired_op_rate_time; double actual_rate; double compute_val = (double)0; long long recs_per_buffer,traj_size; off64_t i; off64_t written_so_far, read_so_far, re_written_so_far, re_read_so_far; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ char *maddr=0; char *wmaddr=0; char now_string[30]; volatile char *buffer1; int anwser,bind_cpu; long wval; char tmpname[256]; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif /*****************/ /* Children only */ /*****************/ if(compute_flag) delay=compute_time; hist_time=thread_qtime_stop=thread_qtime_start=0; thread_rrqfd=r_traj_fd=thread_Lwqfd=(FILE *)0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; r_traj_bytes_completed=r_traj_ops_completed=0; written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(r_traj_flag) { filebytes64 = r_traj_fsize; numrecs64=r_traj_ops; } else { filebytes64 = numrecs64*reclen; } if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } if(oflag) flags=O_RDONLY|O_SYNC; else flags=O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); SetFilePointer(hand,(LONG)0,0,FILE_BEGIN); } else { #endif if((fd = I_OPEN(dummyfile[xx], ((int)flags),0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(135); } #if defined(Windows) } #endif #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,(filebytes64),0,PROT_READ); } if(r_traj_flag) r_traj_fd=open_r_traj(); if(fetchon) fetchit(nbuff,reclen); if(Q_flag) { sprintf(tmpname,"Child_%d_rrol.dat",(int)xx); thread_rrqfd=fopen(tmpname,"a"); if(thread_rrqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_rrqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Reread test start: ",now_string); } child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else /* Wait for signal from parent */ while(child_stat->flag!=CHILD_STATE_BEGIN) Poll((long long)1); if(file_lock) if(mylockf((int) fd, (int) 1, (int)1) != 0) printf("File lock for read failed. %d\n",errno); starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } if(r_traj_flag) rewind(r_traj_fd); for(i=0; iflag = CHILD_STATE_HOLD; exit(137); } } } if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(138); } } else { if(verify_buffer(nbuff,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(139); } } } if(async_flag && no_copy_flag) async_release(gc); re_read_so_far+=reclen/1024; r_traj_bytes_completed+=reclen; r_traj_ops_completed++; if(*stop_flag) { re_read_so_far-=reclen/1024; r_traj_bytes_completed-=reclen; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rrqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_rrqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)1)) printf("Read unlock failed. %d\n",errno); /*fsync(fd);*/ #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*re_read_so_far=(re_read_so_far*1024)/reclen;*/ re_read_so_far=r_traj_ops_completed; } child_stat->throughput = re_read_so_far/child_stat->throughput; child_stat->actual = re_read_so_far; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) { tell_master_stats(THREAD_REREAD_TEST,chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(filebytes64),MS_SYNC); mmap_end(maddr,(unsigned long long)filebytes64); }else fsync(fd); #if defined(Windows) if(unbuffered) CloseHandle(hand); else #endif close(fd); } if(Q_flag && (thread_rrqfd !=0) ) fclose(thread_rrqfd); free(dummyfile[xx]); if(r_traj_flag) fclose(r_traj_fd); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",xx); #else printf("\nChild finished %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Reread test finished: ",now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Reread",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* Thread_reverse_perf_test */ /* Reverse read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_reverse_read_test(int x) #else void * thread_reverse_read_test(x) #endif { long long xx,xx2; char *nbuff; struct child_stats *child_stat; int fd; long long flags = 0; double walltime, cputime; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; double starttime2 = 0; float delay = 0; double temp_time; double compute_val = (double)0; long long recs_per_buffer; off64_t i,t_offset; off64_t lock_offset=0; off64_t current_position=0; off64_t written_so_far, reverse_read, re_read_so_far,read_so_far; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ char *maddr=0; char *wmaddr=0; char now_string[30]; volatile char *buffer1; int anwser,bind_cpu; off64_t traj_offset; char tmpname[256]; FILE *thread_revqfd=0; FILE *thread_Lwqfd=0; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif /*****************/ /* Children only */ /*****************/ if(compute_flag) delay=compute_time; hist_time=thread_qtime_stop=thread_qtime_start=0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; written_so_far=read_so_far=reverse_read=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",xx); #else printf("\nStarting child %lld\n",xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),xx); #else printf("\nStarting process %d slot %lld\n",getpid(),xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],xx2); #endif } if(oflag) flags=O_RDONLY|O_SYNC; else flags=O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); } #endif if((fd = I_OPEN(dummyfile[xx], ((int)flags),0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(140); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,(numrecs64*reclen),0,PROT_READ); } if(fetchon) fetchit(nbuff,reclen); if(Q_flag) { sprintf(tmpname,"Child_%d_revol.dat",(int)xx); thread_revqfd=fopen(tmpname,"a"); if(thread_revqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_revqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Reverse read start: ",now_string); } child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } starttime2 = time_so_far(); if(cpuutilflag) { walltime = starttime2; cputime = cputime_so_far(); } t_offset = (off64_t)reclen; if (!(h_flag || k_flag || mmapflag)) { if(check_filename(dummyfile[xx])) { if((I_LSEEK( fd, -t_offset, SEEK_END ))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror("lseek"); exit(142); } } else { if(I_LSEEK( fd, (numrecs64*reclen)-t_offset, SEEK_SET )<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror("lseek"); exit(77); } } } current_position=(reclen*numrecs64)-reclen; if(file_lock) if(mylockf((int) fd, (int) 1, (int)1)!=0) printf("File lock for read failed. %d\n",errno); for(i=0; iflag = CHILD_STATE_HOLD; exit(144); } } } if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)(current_position/reclen),reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(145); } } else { if(verify_buffer(nbuff,reclen,(off64_t)(current_position/reclen),reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(146); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } current_position+=reclen; if(async_flag && no_copy_flag) async_release(gc); t_offset = (off64_t)reclen*2; if (!(h_flag || k_flag || mmapflag)) { I_LSEEK( fd, -t_offset, SEEK_CUR ); } current_position-=(2 *reclen); reverse_read +=reclen/1024; if(*stop_flag) { reverse_read -=reclen/1024; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_revqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_revqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } } if(file_lock) if(mylockf((int) fd,(int)0, (int)1)) printf("Read unlock failed %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(numrecs64*reclen),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)numrecs64*reclen); } close(fd); } temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime2)-time_res); else child_stat->throughput = ((temp_time - starttime2)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ reverse_read=(reverse_read*1024)/reclen; } child_stat->throughput = reverse_read/child_stat->throughput; child_stat->actual = reverse_read; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_REVERSE_READ_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(numrecs64*reclen),MS_SYNC); mmap_end(maddr,(unsigned long long)numrecs64*reclen); }else fsync(fd); close(fd); } free(dummyfile[xx]); if(Q_flag && (thread_revqfd !=0) ) fclose(thread_revqfd); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Reverse read finished: ", now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Read Backwards",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* Thread_stride_read_test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_stride_read_test(int x) #else void * thread_stride_read_test(x) #endif { long long xx,xx2; char *nbuff=0; struct child_stats *child_stat; double walltime, cputime; int fd; long long flags = 0; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; double starttime2 = 0; float delay = 0; double compute_val = (double)0; double temp_time; long long recs_per_buffer; off64_t i; off64_t lock_offset=0; off64_t savepos64=0; off64_t written_so_far, stride_read,re_read_so_far,read_so_far; off64_t stripewrap = 0; off64_t current_position = 0; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ char *maddr=0; char *wmaddr=0; volatile char *buffer1; int anwser,bind_cpu; off64_t traj_offset; char tmpname[256]; char now_string[30]; FILE *thread_strqfd=0; FILE *thread_Lwqfd=0; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif /*****************/ /* Children only */ /*****************/ if(compute_flag) delay=compute_time; hist_time=thread_qtime_stop=thread_qtime_start=0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; written_so_far=read_so_far=stride_read=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } if(oflag) flags=O_RDONLY|O_SYNC; else flags=O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); } #endif if((fd = I_OPEN(dummyfile[xx], ((int)flags),0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(147); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,(numrecs64*reclen),0,PROT_READ); } if(fetchon) fetchit(nbuff,reclen); if(Q_flag) { sprintf(tmpname,"Child_%d_strol.dat",(int)xx); thread_strqfd=fopen(tmpname,"a"); if(thread_strqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_strqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Stride test start: ", now_string); } child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else /* wait for parent to say go */ while(child_stat->flag!=CHILD_STATE_BEGIN) Poll((long long)1); if(file_lock) if(mylockf((int) fd, (int) 1, (int)1)!=0) printf("File lock for write failed. %d\n",errno); starttime2 = time_so_far(); if(cpuutilflag) { walltime = starttime2; cputime = cputime_so_far(); } for(i=0; iflag = CHILD_STATE_HOLD; exit(149); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } current_position+=reclen; if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)savepos64,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(150); } } else { if(verify_buffer(nbuff,reclen,(off64_t)savepos64,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(151); } } } if(async_flag && no_copy_flag) async_release(gc); if(current_position + (stride * reclen) >= (numrecs64 * reclen)-reclen) { current_position=0; stripewrap++; if(numrecs64 <= stride) { current_position=0; } else { current_position = (off64_t)((stripewrap)%numrecs64)*reclen; } if (!(h_flag || k_flag || mmapflag)) { if(I_LSEEK(fd,current_position,SEEK_SET)<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror("lseek"); exit(152); } } } else { current_position+=(stride*reclen)-reclen; if (!(h_flag || k_flag || mmapflag)) { if(I_LSEEK(fd,current_position,SEEK_SET)<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror("lseek"); exit(154); }; } } stride_read +=reclen/1024; if(*stop_flag) { stride_read -=reclen/1024; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_strqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_strqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } } if(file_lock) if(mylockf((int) fd,(int)0,(int)1)) printf("Read unlock failed %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(numrecs64*reclen),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)numrecs64*reclen); } close(fd); } temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime2)-time_res); else child_stat->throughput = ((temp_time - starttime2)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ stride_read=(stride_read*1024)/reclen; } child_stat->throughput = stride_read/child_stat->throughput; child_stat->actual = stride_read; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) { tell_master_stats(THREAD_STRIDE_TEST,chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(numrecs64*reclen),MS_SYNC); mmap_end(maddr,(unsigned long long)numrecs64*reclen); }else fsync(fd); close(fd); } if(Q_flag && (thread_strqfd !=0) ) fclose(thread_strqfd); free(dummyfile[xx]); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Stride test finished: ", now_string); fclose(thread_Lwqfd); } if(hist_summary) dump_hist("Stride Read",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* Thread random test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_mix_test(int x) #else void * thread_mix_test(x) #endif { int selector; int num_readers; long xx; mix_test = 1; #ifdef NO_THREADS xx=chid; #else if(use_thread) { xx = (long)x; } else { xx=(long)chid; } #endif if(pct_read!=0) { num_readers = (pct_read * num_child)/100; if(xx < num_readers) selector=0; else selector=1; } else { if(Kplus_flag) { if(xx+1 <= Kplus_readers) selector=0; else selector=1; } else { /* Simple round robin */ selector= ((int)xx) % 2; } } if(selector==0) { if(seq_mix) thread_read_test((int)x); else thread_ranread_test((int)x); } else { if(seq_mix) thread_write_test((int)x); else thread_ranwrite_test((int)x); } return(0); } /************************************************************************/ /* Thread random read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_ranread_test(int x) #else void * thread_ranread_test(x) void *x; #endif { long long xx,xx2; struct child_stats *child_stat; double walltime, cputime; int fd; long long flags = 0; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; double starttime1 = 0; float delay = 0; double temp_time; double compute_val = (double)0; off64_t written_so_far, ranread_so_far, re_written_so_far,re_read_so_far; long long recs_per_buffer; off64_t current_offset=0; off64_t i; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ char *nbuff=0; char *maddr=0; char *wmaddr=0; volatile char *buffer1; int anwser,bind_cpu; off64_t traj_offset; off64_t lock_offset=0; char tmpname[256]; char now_string[30]; FILE *thread_randrfd=0; FILE *thread_Lwqfd=0; long long *recnum=0; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif long long save_pos; #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; #endif unsigned long long big_rand; #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif #ifdef MERSENNE unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}, length=4; #endif #ifdef MERSENNE init_by_array64(init, length); #else #ifdef bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #endif #endif #endif recnum = (long long *)malloc(sizeof(*recnum)*numrecs64); if (recnum){ /* pre-compute random sequence based on Fischer-Yates (Knuth) card shuffle */ for(i = 0; i < numrecs64; i++){ recnum[i] = i; } for(i = numrecs64-1; i >= 0; i--) { long long tmp = recnum[i]; #ifdef MERSENNE big_rand = genrand64_int64(); #else #ifdef bsd4_2 rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); #else #ifdef Windows rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); #else big_rand = lrand48(); #endif #endif #endif big_rand = big_rand % (i+1); tmp = recnum[i]; recnum[i] = recnum[big_rand]; recnum[big_rand] = tmp; } } else { fprintf(stderr,"Random uniqueness fallback.\n"); } if(compute_flag) delay=compute_time; hist_time=thread_qtime_stop=thread_qtime_start=0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; written_so_far=ranread_so_far=re_written_so_far=re_read_so_far=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } if(oflag) { flags=O_RDONLY|O_SYNC; } else flags=O_RDONLY; #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); } #endif if((fd = I_OPEN(dummyfile[xx], ((int)flags),0))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); perror(dummyfile[xx]); exit(156); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif if(mmapflag) { maddr=(char *)initfile(fd,(numrecs64*reclen),0,PROT_READ); } child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; if(debug1) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } /*****************/ /* Children only */ /*****************/ if(fetchon) fetchit(nbuff,reclen); if(Q_flag) { sprintf(tmpname,"Child_%d_randrol.dat",(int)xx); thread_randrfd=fopen(tmpname,"a"); if(thread_randrfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_randrfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Random read start: ", now_string); } child_stat=(struct child_stats *)&shmaddr[xx]; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } #ifdef MERSENNE init_by_array64(init, length); #else #ifdef bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #endif #endif #endif if(file_lock) if(mylockf((int) fd, (int) 1, (int)1)!=0) printf("File lock for read failed. %d\n",errno); for(i=0; iflag = CHILD_STATE_HOLD; exit(160); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)1, lock_offset, reclen); } save_pos=current_offset/reclen; current_offset+=reclen; if(verify){ if(async_flag && no_copy_flag) { if(verify_buffer(buffer1,reclen,(off64_t)save_pos,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(161); } } else { if(verify_buffer(nbuff,reclen,(off64_t)save_pos,reclen,(long long)pattern,sverify)){ if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(162); } } } if(async_flag && no_copy_flag) async_release(gc); ranread_so_far+=reclen/1024; if(*stop_flag) { ranread_so_far-=reclen/1024; } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_randrfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_randrfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } } if(file_lock) if(mylockf((int) fd,(int)0,(int)1)) printf("Read unlock failed %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(include_flush) { if(mmapflag) { msync(maddr,(size_t)(numrecs64*reclen),MS_SYNC); }else fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)numrecs64*reclen); } close(fd); } temp_time = time_so_far(); child_stat=(struct child_stats *)&shmaddr[xx]; if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ ranread_so_far=(ranread_so_far*1024)/reclen; } child_stat->throughput = ranread_so_far/child_stat->throughput; child_stat->actual = ranread_so_far; if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_RANDOM_READ_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(!include_close) { if(mmapflag) { msync(maddr,(size_t)(numrecs64*reclen),MS_SYNC); mmap_end(maddr,(unsigned long long)numrecs64*reclen); }else fsync(fd); close(fd); } if(Q_flag && (thread_randrfd !=0) ) fclose(thread_randrfd); free(dummyfile[xx]); if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Random read finished: ",now_string); fclose(thread_Lwqfd); } if(recnum) free(recnum); if(hist_summary) dump_hist("Random Read",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* Thread random write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_ranwrite_test(int x) #else void * thread_ranwrite_test( x) #endif { struct child_stats *child_stat; double starttime1 = 0; double temp_time; double walltime, cputime; double compute_val = (double)0; float delay = (double)0; double thread_qtime_stop,thread_qtime_start; double hist_time; double desired_op_rate_time; double actual_rate; off64_t traj_offset; off64_t current_offset=0; long long flags; long long w_traj_bytes_completed; long long w_traj_ops_completed; int fd; long long recs_per_buffer; long long stopped,i; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long xx,xx2; char *dummyfile [MAXSTREAMS]; /* name of dummy file */ char *nbuff=0; char *maddr=0; char *wmaddr=0; char *free_addr=0; int anwser,bind_cpu,wval; off64_t filebytes64; off64_t lock_offset=0; char tmpname[256]; char now_string[30]; FILE *thread_randwqfd=0; FILE *thread_Lwqfd=0; long long *recnum = 0; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; #endif unsigned long long big_rand; #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif #ifdef MERSENNE unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}, length=4; #endif double burst_acc_time_sec = 0; if(compute_flag) delay=compute_time; hist_time=thread_qtime_stop=thread_qtime_start=0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; filebytes64 = numrecs64*reclen; written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; w_traj_bytes_completed=w_traj_ops_completed=0; recs_per_buffer = cache_size/reclen ; #ifdef MERSENNE init_by_array64(init, length); #else #ifdef bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #endif #endif #endif recnum = (long long *) malloc(sizeof(*recnum)*numrecs64); if (recnum){ /* pre-compute random sequence based on Fischer-Yates (Knuth) card shuffle */ for(i = 0; i < numrecs64; i++){ recnum[i] = i; } for(i = numrecs64-1; i >= 0; i--) { long long tmp = recnum[i]; #ifdef MERSENNE big_rand = genrand64_int64(); #else #ifdef bsd4_2 rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); #else #ifdef Windows rand1=(long long)rand(); rand2=(long long)rand(); rand3=(long long)rand(); big_rand=(rand1<<32)|(rand2<<16)|(rand3); #else big_rand = lrand48(); #endif #endif #endif big_rand = big_rand % (i+1); tmp = recnum[i]; recnum[i] = recnum[big_rand]; recnum[big_rand] = tmp; } } else { fprintf(stderr,"Random uniqueness fallback.\n"); } #ifdef NO_THREADS xx=chid; #else if(use_thread) { xx = (long long)((long)x); } else { xx=chid; } #endif #ifndef NO_THREADS #if defined( _HPUX_SOURCE ) || defined ( linux ) if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; #if defined(_HPUX_SOURCE) pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(bind_cpu, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpuset),&cpuset); #endif my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1 ) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],(long)xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],(long long)xx2); #endif } /*****************/ /* Children only */ /*******************************************************************/ /* Random write throughput performance test. **********************/ /*******************************************************************/ if(oflag) flags=O_RDWR|O_SYNC|O_CREAT; else flags=O_RDWR|O_CREAT; #if defined(O_DSYNC) if(odsync) flags |= O_DSYNC; #endif #if defined(_HPUX_SOURCE) || defined(linux) if(read_sync) flags |=O_RSYNC|O_SYNC; #endif #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) if(direct_flag) flags |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags |=O_DIRECTIO; #endif #endif #if defined(Windows) if(unbuffered) { hand=CreateFile(dummyfile[xx], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING| FILE_FLAG_WRITE_THROUGH|FILE_FLAG_POSIX_SEMANTICS, NULL); } #endif if((fd = I_OPEN(dummyfile[xx], ((int)flags),0640))<0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("\nCan not open temp file: %s\n", dummyfile[xx]); perror("open"); exit(125); } #ifdef VXFS if(direct_flag) { ioctl(fd,VX_SETCACHE,VX_DIRECT); ioctl(fd,VX_GETCACHE,&test_foo); if(test_foo == 0) { if(!client_iozone) printf("\nVxFS advanced setcache feature not available.\n"); exit(3); } } #endif #if defined(solaris) if(direct_flag) { test_foo = directio(fd, DIRECTIO_ON); if(test_foo != 0) { if(!client_iozone) printf("\ndirectio not available.\n"); exit(3); } } #endif #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif if(mmapflag) { maddr=(char *)initfile(fd,(filebytes64),1,PROT_READ|PROT_WRITE); } if(reclen < cache_size ) { recs_per_buffer = cache_size/reclen ; nbuff=&nbuff[(xx%recs_per_buffer)*reclen]; } if(fetchon) /* Prefetch into processor cache */ fetchit(nbuff,reclen); child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag=CHILD_STATE_READY; /* Tell parent child is ready to go */ if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } written_so_far=0; child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->actual = 0; child_stat->throughput = 0; stopped=0; if(file_lock) if(mylockf((int) fd, (int) 1, (int)0) != 0) printf("File lock for write failed. %d\n",errno); if(Q_flag) { sprintf(tmpname,"Child_%d_randwol.dat",(int)xx); thread_randwqfd=fopen(tmpname,"a"); if(thread_randwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_randwqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Random write start: ", now_string); } if((verify && !no_copy_flag) || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } for(i=0; ithroughput = (time_so_far() - starttime1)-time_res - burst_acc_time_sec; if(child_stat->throughput < (double).000001) { child_stat->throughput = time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; if(debug1) { printf("\n(%ld) Stopped by another\n", (long)xx); } stopped=1; } if(purge) purgeit(nbuff,reclen); if(Q_flag || hist_summary) { thread_qtime_start=time_so_far(); } again: if(mmapflag) { wmaddr = &maddr[current_offset]; fill_area((long long*)nbuff,(long long*)wmaddr,(long long)reclen); if(!mmapnsflag) { if(mmapasflag) msync(wmaddr,(size_t)reclen,MS_ASYNC); if(mmapssflag) msync(wmaddr,(size_t)reclen,MS_SYNC); } } else { if(async_flag) { if(no_copy_flag) { free_addr=nbuff=(char *)malloc((size_t)reclen+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); if(verify || dedup_flag || dedup_iflag) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)(current_offset/reclen)); async_write_no_copy(gc, (long long)fd, nbuff, reclen, (current_offset), depth,free_addr); } else async_write(gc, (long long)fd, nbuff, reclen, current_offset, depth); } else { wval = write(fd, nbuff, (size_t) reclen); #ifndef NO_THREADS count_burst(&burst_acc_time_sec, xx); #endif if(wval != reclen) { if(*stop_flag && !stopped){ if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } temp_time = time_so_far(); child_stat->throughput = (temp_time - starttime1)-time_res - burst_acc_time_sec; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; if(debug1) { printf("\n(%ld) Stopped by another\n", (long)xx); } stopped=1; goto again; } /* Note: Writer must finish even though told to stop. Otherwise the readers will fail. The code will capture bytes transfered before told to stop but let the writer complete. */ #ifdef NO_PRINT_LLD printf("\nError writing block %ld, fd= %d\n", (long)i, fd); #else printf("\nError writing block %lld, fd= %d\n", (long long)i, fd); #endif if(wval==-1) perror("write"); if (!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat->flag = CHILD_STATE_HOLD; exit(127); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start-time_res); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); /* printf("Desired rate %g Actual rate %g Nap %g microseconds\n",desired_op_rate_time, actual_rate, (desired_op_rate_time-actual_rate)); */ if( actual_rate < desired_op_rate_time) my_unap((unsigned long long) ((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_randwqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_randwqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } w_traj_ops_completed++; w_traj_bytes_completed+=reclen; written_so_far+=reclen/1024; if(*stop_flag) { written_so_far-=reclen/1024; w_traj_bytes_completed-=reclen; } } if(file_lock) if(mylockf((int) fd, (int) 0, (int)0)) printf("Write unlock failed. %d\n",errno); #ifdef ASYNC_IO if(async_flag) { end_async(gc); gc=0; } #endif if(!xflag) { *stop_flag=1; if(distributed && client_iozone) send_stop(); } if(include_flush) { if(mmapflag) msync(maddr,(size_t)filebytes64,MS_SYNC); else fsync(fd); } if(include_close) { if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); close(fd); } if(!stopped){ temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec); else child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(cdebug) { fprintf(newstdout,"Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); fflush(newstdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_RANDOM_WRITE_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); stopped=0; /*******************************************************************/ /* End random write performance test. ******************************/ /*******************************************************************/ if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(!include_close) { if(mmapflag) { msync(maddr,(size_t)numrecs64*reclen,MS_SYNC); /*Clean up before read starts running*/ mmap_end(maddr,(unsigned long long)numrecs64*reclen); }else fsync(fd); close(fd); } if(Q_flag && (thread_randwqfd !=0) ) fclose(thread_randwqfd); free(dummyfile[xx]); if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Random write finished: ", now_string); fclose(thread_Lwqfd); } if(recnum) free(recnum); if(hist_summary) dump_hist("Random Write",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* Thread cleanup test */ /* This is not a measurement. It is a mechanism to cleanup all of the */ /* temporary files that were being used. This becomes very important */ /* when testing multiple clients over a network :-) */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_cleanup_test(int x) #else void * thread_cleanup_test(x) #endif { long long xx; struct child_stats *child_stat; char *dummyfile[MAXSTREAMS]; /* name of dummy file */ #ifdef NO_THREADS xx=chid; #else if(use_thread) xx = (long long)((long)x); else { xx=chid; } #endif dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx]); #else sprintf(dummyfile[xx],"%s",filearray[xx]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx],(long)xx); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx],(long long)xx); #endif } if(!no_unlink) { if(check_filename(dummyfile[xx])) unlink(dummyfile[xx]); } child_stat = (struct child_stats *)&shmaddr[xx]; /*****************/ /* Children only */ /*****************/ child_stat=(struct child_stats *)&shmaddr[xx]; child_stat->flag = CHILD_STATE_READY; if(distributed && client_iozone) { tell_master_ready(chid); wait_for_master_go(chid); } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } *stop_flag=1; if(distributed && client_iozone) send_stop(); if(distributed && client_iozone) tell_master_stats(THREAD_CLEANUP_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ free(dummyfile[xx]); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } /************************************************************************/ /* mythread_create() Internal routine that calls pthread_create() */ /************************************************************************/ #ifndef NO_THREADS #ifdef HAVE_ANSIC_C long long mythread_create( void *(*func)(void *),int x) #else long long mythread_create( func,x) void *func; int x; #endif { pthread_t ts; pthread_attr_t attr; int xx; long long meme; void *myptr; char foo[10]; /* mythread_create( void *(*func)(void *),int x) */ /* DAMN COMPILERS !!! */ sprintf(foo,"%x",x); sscanf(foo,"%llx",&meme); sscanf(foo,"%p",&myptr); #ifdef OSFV3 xx=(int )pthread_create(&ts, pthread_attr_default, (void *)(func), myptr); #else pthread_attr_init(&attr); xx=(int )pthread_create((pthread_t *)&ts, (pthread_attr_t *) &attr, (void *(*)(void *))(func), myptr); #endif bcopy(&ts,&p_childids[meme],sizeof(pthread_t)); if(xx < (int)0) printf("Thread create failed. Returned %d Errno = %d\n",xx,errno); if(debug1 ) { printf("\nthread created has an id of %p\n",(void *)&ts); #ifdef NO_PRINT_LLD printf("meme %ld\n",(long)meme); #else printf("meme %lld\n",(long long)meme); #endif } return((long long)meme); } #else #ifdef HAVE_ANSIC_C long long mythread_create( void *(*func)(void *),int x) #else long long mythread_create( func, x) void *(*func)(void *); int x; #endif { printf("This version does not support threads\n"); return(-1); } #endif /************************************************************************/ /* thread_exit() Internal routine that calls pthread_exit() */ /************************************************************************/ #ifndef NO_THREADS #ifdef HAVE_ANSIC_C int thread_exit(void) #else int thread_exit() #endif { pthread_exit((void *)NULL); #if !defined(solaris) return(0); #endif } #else #ifdef HAVE_ANSIC_C int thread_exit(void) #else int thread_exit() #endif { printf("This version does not support threads\n"); return(-1); } #endif /************************************************************************/ /* mythread_self() Internal function that calls pthread_self() */ /************************************************************************/ #ifndef NO_THREADS #ifdef HAVE_ANSIC_C pthread_t mythread_self(void) #else pthread_t mythread_self() #endif { pthread_t xx; xx = pthread_self(); return(xx); } #else #ifdef HAVE_ANSIC_C int mythread_self(void) #else int mythread_self() #endif { printf("This version does not support threads\n"); return(-1); } #endif /************************************************************************/ /* Internal thread_join routine... calls pthread_join */ /************************************************************************/ #ifndef NO_THREADS #ifdef HAVE_ANSIC_C void * thread_join( long long tid, void *status) #else void * thread_join( tid, status) long long tid; void *status; #endif { int xx; pthread_t eek; pthread_attr_t foo; bcopy(&p_childids[tid],&eek,sizeof(pthread_t)); xx=pthread_join(eek,(void **)&foo); if(xx<0) printf("Thread join returned error %d\n",errno); return(0); } #else #ifdef HAVE_ANSIC_C void * thread_join( long long tid, void *status) #else void * thread_join( tid, status) long long tid; void *status; #endif { printf("This version does not support threads\n"); return((void *)-1); } #endif /************************************************************************/ /* Dump the CPU utilization data. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void dump_throughput_cpu(void) #else void dump_throughput_cpu() #endif { long long x,y,i,j; char *port; char *label; char print_str[300]; x=max_x; y=max_y; port = use_thread ? "threads" : "processes"; printf("\n\"CPU utilization report Y-axis is type of test X-axis is number of %s\"\n",port); if (bif_flag) { sprintf(print_str, "CPU utilization report Y-axis is type of test X-axis is number of %s", port); do_label(bif_fd, print_str, bif_row++, bif_column); } label = OPS_flag ? "ops/sec" : MS_flag ? "microseconds/op" : "kBytes/sec"; #ifdef NO_PRINT_LLD if(!silent) printf("\"Record size = %ld kBytes \"\n", (long)(reclen/1024)); #else if(!silent) printf("\"Record size = %lld kBytes \"\n", (long long)(reclen/1024)); #endif if(!silent) printf("\"Output is in CPU%%\"\n\n"); if (bif_flag) { #ifdef NO_PRINT_LLD sprintf(print_str, "Record size = %ld kBytes", (long)(reclen/1024)); #else sprintf(print_str, "Record size = %lld kBytes", (long long)(reclen/1024)); #endif do_label(bif_fd, print_str, bif_row++, bif_column); sprintf(print_str, "Output is in CPU%%"); do_label(bif_fd, print_str, bif_row++, bif_column); } for (i = 0; i < x; i++) { if(!silent) printf("\"%15s \"", throughput_tests[i]); if (bif_flag) { sprintf(print_str, "%15s ", throughput_tests[i]); do_label(bif_fd, print_str, bif_row, bif_column++); bif_column++; } for (j = 0; j <= y; j++) { if (bif_flag) do_float(bif_fd, runtimes[i][j].cpuutil, bif_row, bif_column++); if(!silent) printf(" %10.2f ", runtimes[i][j].cpuutil); } if(!silent) printf("\n\n"); if (bif_flag) { bif_column=0; bif_row++; } } } /************************************************************************/ /* Dump the throughput graphs */ /************************************************************************/ #ifdef HAVE_ANSIC_C void dump_throughput(void) #else void dump_throughput() #endif { long long x,y,i,j; char *port; char *label; char print_str[300]; x=max_x; y=max_y; if(use_thread) port="threads"; else port="processes"; if(!silent) printf("\n\"Throughput report Y-axis is type of test X-axis is number of %s\"\n",port); if(bif_flag) { bif_fd=create_xls(bif_filename); do_label(bif_fd,command_line,bif_row++,bif_column); sprintf(print_str,"Throughput report Y-axis is type of test X-axis is number of %s",port); do_label(bif_fd,print_str,bif_row++,bif_column); } if(OPS_flag) label="ops/sec"; else if(MS_flag) label="microseconds/op"; else label="kBytes/sec"; #ifdef NO_PRINT_LLD if(!silent) printf("\"Record size = %ld kBytes \"\n",(long)(reclen/1024)); #else if(!silent) printf("\"Record size = %lld kBytes \"\n",(long long)(reclen/1024)); #endif if(!silent) printf("\"Output is in %s\"\n\n",label); if(bif_flag) { #ifdef NO_PRINT_LLD sprintf(print_str,"Record size = %ld kBytes",(long)(reclen/1024)); #else sprintf(print_str,"Record size = %lld kBytes",(long long)(reclen/1024)); #endif do_label(bif_fd,print_str,bif_row++,bif_column); sprintf(print_str,"Output is in %s",label); do_label(bif_fd,print_str,bif_row++,bif_column); } for(i=0;i<=toutputindex;i++) { if(!silent) printf("\"%15s \"",toutput[i]); if(bif_flag) { sprintf(print_str,"%15s ",toutput[i]); do_label(bif_fd,print_str,bif_row,bif_column++); bif_column++; } for(j=0;j<=y;j++) { if(bif_flag) { do_float(bif_fd,(double)report_darray[i][j],bif_row,bif_column++); } if(!silent) printf(" %10.2f ",report_darray[i][j]); } if(!silent) printf("\n\n"); if(bif_flag) { bif_column=0; bif_row++; } } if (cpuutilflag) dump_throughput_cpu(); if(bif_flag) close_xls(bif_fd); } /************************************************************************/ /* store_dvalue() */ /* Stores a value in an in memory array. Used by the report function */ /* to re-organize the output for Excel */ /************************************************************************/ #ifdef HAVE_ANSIC_C void store_dvalue(double value) #else void store_dvalue(value) double value; #endif { report_darray[current_x][current_y]=value; current_x++; if(current_x > max_x) max_x=current_x; if(current_y > max_y) max_y=current_y; if(max_x >= MAX_X) { printf("\nMAX_X too small\n"); exit(163); } if(max_y >= MAXSTREAMS) { printf("\nMAXSTREAMS too small\n"); exit(164); } } /************************************************************************/ /* Initialize a file that will be used by mmap. */ /************************************************************************/ #ifdef HAVE_ANSIC_C char * initfile(int fd, off64_t filebytes,int flag,int prot) #else char * initfile(fd, filebytes,flag, prot) int fd; off64_t filebytes; int flag, prot; #endif { char *pa; int mflags=0; long long x; char *tmp,*stmp; int file_flags; long long recs; long long i; int dflag = 0; if(flag) { #ifdef _HPUX_SOURCE /* * Save time, just have the operating system prealloc * the file */ prealloc(fd,filebytes); #else /* * Allocate a temporary buffer to meet any alignment * contraints of any method. */ tmp=(char *)malloc((size_t)reclen * 2); stmp=tmp; /* * Align to a reclen boundary. */ tmp = (char *)((((long)tmp + (long)reclen))& ~(((long)reclen-1))); /* * Special case.. Open O_DIRECT, and going to be mmap() * Under Linux, one can not create a sparse file using * a file that is opened with O_DIRECT */ file_flags=fcntl(fd,F_GETFL); #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) || defined(Windows) || defined (__FreeBSD__) dflag = O_DIRECT; #endif #if defined(TRU64) if(direct_flag) dflag = O_DIRECTIO; #endif #endif if((file_flags & dflag) !=0) { recs=filebytes/reclen; for (i =0; i microsecs) break; } } /************************************************************************/ /* Function that establishes the resolution */ /* of the gettimeofday() function. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void get_resolution(void) #else void get_resolution() #endif { double starttime, finishtime, besttime = 0; long j,delay; int k; finishtime=time_so_far1(); /* Warm up the instruction cache */ starttime=time_so_far1(); /* Warm up the instruction cache */ delay=j=0; /* Warm up the data cache */ for(k=0;k<10;k++) { while(1) { starttime=time_so_far1(); for(j=0;j< delay;j++) ; finishtime=time_so_far1(); if(starttime==finishtime) delay++; else { if(k==0) besttime=(finishtime-starttime); if((finishtime-starttime) < besttime) besttime=(finishtime-starttime); break; } } } time_res=besttime/1000000.0; } /************************************************************************/ /* Function that establishes the resolution */ /* of the getrusage() function. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void get_rusage_resolution(void) #else void get_rusage_resolution() #endif { double starttime, finishtime; long j; finishtime=cputime_so_far(); /* Warm up the instruction cache */ starttime=cputime_so_far(); /* Warm up the instruction cache */ delay=j=0; /* Warm up the data cache */ while(1) { starttime=cputime_so_far(); for(j=0;j< delay;j++) ; finishtime=cputime_so_far(); if(starttime==finishtime) delay++; else break; } cputime_res = (finishtime-starttime); /* in seconds */ } /************************************************************************/ /* Time measurement routines. */ /* Return time in microseconds */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double time_so_far1(void) #else static double time_so_far1() #endif { /* For Windows the time_of_day() is useless. It increments in 55 milli second increments. By using the Win32api one can get access to the high performance measurement interfaces. With this one can get back into the 8 to 9 microsecond resolution */ #ifdef Windows LARGE_INTEGER freq,counter; double wintime; double bigcounter; struct timeval tp; if(pit_hostname[0]){ pit_gettimeofday(&tp, (struct timezone *) NULL, pit_hostname, pit_service); return ((double) (tp.tv_sec)*1000000.0)+(((double)tp.tv_usec)); } else { QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&counter); bigcounter=(double)counter.HighPart *(double)0xffffffff + (double)counter.LowPart; wintime = (double)(bigcounter/(double)freq.LowPart); return((double)wintime*1000000.0); } #else #if defined (OSFV4) || defined(OSFV3) || defined(OSFV5) struct timespec gp; if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1) perror("getclock"); return (( (double) (gp.tv_sec)*1000000.0) + ( ((float)(gp.tv_nsec)) * 0.001 )); #else struct timeval tp; if(pit_hostname[0]){ if (pit_gettimeofday(&tp, (struct timezone *) NULL, pit_hostname, pit_service) == -1) perror("pit_gettimeofday"); return ((double) (tp.tv_sec)*1000000.0) + (((double) tp.tv_usec) ); } else { if (gettimeofday(&tp, (struct timezone *) NULL) == -1) perror("gettimeofday"); return ((double) (tp.tv_sec)*1000000.0) + (((double) tp.tv_usec) ); } #endif #endif } /************************************************************************/ /* Return the clocks per tick for the times() call. */ /************************************************************************/ #ifdef unix #ifdef HAVE_ANSIC_C static double clk_tck(void) /* Get the clocks per tick for times */ #else static double clk_tck() /* Get the clocks per tick for times */ #endif { return((double)sysconf(_SC_CLK_TCK)); } /************************************************************************/ /* Return the user time in tics as a double. */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double utime_so_far(void) /* Return user time in ticks as double */ #else static double utime_so_far() #endif { struct tms tp; times(&tp); return ((double) (tp.tms_utime)); } /************************************************************************/ /* Return the system time in tics as a double. */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double stime_so_far(void) /* Return system time in ticks as double */ #else static double stime_so_far() #endif { struct tms tp; times(&tp); return ((double) (tp.tms_stime)); } /************************************************************************/ /* Return the CPU (user + system) time in seconds as a double. */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double cputime_so_far(void) /* Return CPU time in seconds as double */ #else static double cputime_so_far() #endif { #if 0 struct tms tp; times(&tp); return ((double) (tp.tms_utime + tp.tms_stime) / sc_clk_tck); #else struct rusage ru; if (getrusage (RUSAGE_SELF, &ru)) perror ("getrusage"); return ((double)(ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) + .000001 *(ru.ru_utime.tv_usec + ru.ru_stime.tv_usec)); #endif } #endif /************************************************************************/ /* Return the CPU utilization ((user + system) / walltime) as a percentage. */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double cpu_util(double cputime, double walltime) #else static double cpu_util(cputime, walltime) double cputime, walltime; #endif { double cpu; if (walltime <= (double)0.0) { cpu = (double)0.0; return cpu; } if (cputime <= (double)0.0) cputime = 0.0; if (walltime <= (double)0.0) cpu = (double)100.0; else { cpu = (((double)100.0 * cputime) / walltime); /* if (cpu > (double)100.0) cpu = (double)99.99; */ } return cpu; } /************************************************************************/ /* This is a locking function that permits the writes and */ /* reads during the test to hold a file lock. Since each */ /* tmp file that Iozone creates is a private file, this seems */ /* like a no-op but it turns out that when using Iozone */ /* over NFS, life is very, very different. Some vendors */ /* read and write performance goes to zip when locks are held */ /* even if there is only one process using the file and having */ /* it locked. Some implementations of NFS transition from async */ /* to fully sync reads and writes if any locks are used. Euck... */ /************************************************************************/ #ifdef HAVE_ANSIC_C int mylockf(int fd, int op, int rdwr) #else int mylockf(fd, op, rdwr) int fd, op, rdwr; #endif { struct flock myflock; int ret; if(op==0) /* Generic unlock the whole file */ { myflock.l_type=F_UNLCK; myflock.l_whence=SEEK_SET; myflock.l_start=0; myflock.l_len=0; /* The whole file */ myflock.l_pid=getpid(); ret=fcntl(fd,F_SETLKW, &myflock); } else /* Generic lock the whole file */ { if(rdwr==0) myflock.l_type=F_WRLCK; /* Apply write lock */ else myflock.l_type=F_RDLCK; /* Apply read lock */ myflock.l_whence=SEEK_SET; myflock.l_start=0; myflock.l_len=0; /* The whole file */ myflock.l_pid=getpid(); ret=fcntl(fd,F_SETLKW, &myflock); } return(ret); } #ifdef HAVE_ANSIC_C int mylockr(int fd, int op, int rdwr, off64_t offset, off64_t size) #else int mylockr(fd, op, rdwr, offset, size) int fd, op, rdwr; off64_t offset; off64_t size; #endif { struct flock myflock; int ret; if(op==0) /* Generic unlock the whole file */ { /*printf("Child: %lld Unlock offset %lld size %lld\n",chid,offset,size);*/ myflock.l_type=F_UNLCK; myflock.l_whence=SEEK_SET; myflock.l_start=offset; myflock.l_len=size; /* The whole file */ myflock.l_pid=getpid(); ret=fcntl(fd,F_SETLKW, &myflock); } else /* Generic lock the range */ { if(rdwr==0) { myflock.l_type=F_WRLCK; /* Apply write lock */ /* printf("Write ");*/ } else { myflock.l_type=F_RDLCK; /* Apply read lock */ /* printf("Read ");*/ } /*printf("Child: %lld Lock offset %lld size %lld\n",chid, offset,size);*/ myflock.l_whence=SEEK_SET; myflock.l_start=offset; myflock.l_len=size; /* The whole file */ myflock.l_pid=getpid(); ret=fcntl(fd,F_SETLKW, &myflock); } return(ret); } /************************************************************************/ /* This function is used to simulate compute time that does */ /* not involve the I/O subsystem. */ /************************************************************************/ #ifdef HAVE_ANSIC_C float do_compute(float comp_delay) #else float do_compute(comp_delay) float comp_delay; #endif { double starttime,tmptime; if(comp_delay == (float)0.0) return(0.0); starttime=time_so_far(); while(1) { tmptime=time_so_far()-starttime; if(tmptime >= (double)comp_delay) return(tmptime); } } /************************************************************************/ /* This function is intended to cause an interruption */ /* in the read pattern. It will make a reader have */ /* jitter in its access behavior. */ /* When using direct I/O one must use a pagesize transfer. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void disrupt(int fd) #else void disrupt(fd) int fd; #endif { char *nbuff,*free_addr; off64_t current; free_addr=nbuff=(char *)malloc((size_t)page_size+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); /* Save current position */ current = I_LSEEK(fd,0,SEEK_CUR); /* Move to beginning of file */ I_LSEEK(fd,0,SEEK_SET); /* Read a little of the file */ if(direct_flag) junk=read(fd,nbuff,page_size); else junk=read(fd,nbuff,1); /* Skip into the file */ I_LSEEK(fd,page_size,SEEK_SET); /* Read a little of the file */ if(direct_flag) junk=read(fd,nbuff,page_size); else junk=read(fd,nbuff,1); /* Restore current position in file, before disruption */ I_LSEEK(fd,current,SEEK_SET); free(free_addr); } #if defined(Windows) /************************************************************************/ /* This function is intended to cause an interruption */ /* in the read pattern. It will make a reader have */ /* jitter in its access behavior. */ /* When using direct I/O one must use a pagesize transfer. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void disruptw(HANDLE hand) #else void disruptw(HANDLE) int hand; #endif { char *nbuff,*free_addr; off64_t current; long retval; free_addr=nbuff=(char *)malloc((size_t)page_size+page_size); nbuff=(char *)(((long)nbuff+(long)page_size) & (long)~(page_size-1)); /* Save current position */ current=SetFilePointer(hand,(LONG)0,0,FILE_CURRENT); /* Move to beginning of file */ SetFilePointer(hand,(LONG)0,0,FILE_BEGIN); /* Read a little of the file */ ReadFile(hand, nbuff, reclen,(LPDWORD)&retval,0); /* Skip into the file */ SetFilePointer(hand,(LONG)page_size,0,FILE_BEGIN); /* Read a little of the file */ ReadFile(hand, nbuff, reclen,(LPDWORD)&retval,0); /* Restore current position in file, before disruption */ SetFilePointer(hand,(LONG)current,0,FILE_BEGIN); free(free_addr); } #endif /************************************************************************/ /* Read a telemetry file and return the the offset */ /* for the next operaton. Also, set the size */ /* in the variable given in the param list. */ /* which == 0 ... reader calling */ /* which == 1 ... writer calling */ /************************************************************************/ #ifdef HAVE_ANSIC_C long long get_traj(FILE *traj_fd, long long *traj_size, float *delay, long which) #else long long get_traj(traj_fd, traj_size, delay, which) FILE *traj_fd; long long *traj_size; float *delay; long which; #endif { long long traj_offset = 0; #ifdef NO_PRINT_LLD long tmp1 = 0; long tmp2 = 0; long tmp3 = 0; long tmp4 = 0; #else long long tmp1 = 0; long long tmp2 = 0; long long tmp3 = 0; long long tmp4 = 0; #endif int tmp = 0; int tokens; int ret=0; char *ret1,*where; char buf[200]; char sbuf[200]; int got_line; got_line=0; while(got_line==0) { tokens=0; ret1=fgets(buf,200,traj_fd); if(ret1==(char *)0) { printf("\n\n\tEarly end of telemetry file. Results not accurate.\n"); signal_handler(); } where=(char *)&buf[0]; strcpy(sbuf,buf); if((*where=='#') || (*where=='\n')) continue; tokens++; strtok(where," "); while( (char *)(strtok( (char *)0," ")) != (char *)0) { tokens++; } got_line=1; } if(tokens == 3) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld %d\n",&tmp1,&tmp2,&tmp); traj_offset=(long long)tmp1; *traj_size=(long long)tmp2; #else ret=sscanf(sbuf,"%lld %lld %d\n",&tmp1,&tmp2,&tmp); traj_offset=(long long)tmp1; *traj_size=(long long)tmp2; #endif *delay= ((float)tmp/1000); } if(tokens == 2) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld\n",&tmp3,&tmp4); traj_offset=(long long)tmp3; *traj_size=(long long)tmp4; #else ret=sscanf(sbuf,"%lld %lld\n",&tmp3,&tmp4); traj_offset=(long long)tmp3; *traj_size=(long long)tmp4; #endif *delay=compute_time; /*printf("\nReading %s trajectory with %d items\n",which?"write":"read",tokens);*/ } if((tokens != 2) && (tokens !=3)) { printf("\n\tInvalid entry in telemetry file. > %s <\n",sbuf); exit(178); } if(ret==EOF) { printf("\n\n\tEarly end of telemetry file. Results not accurate.\n"); signal_handler(); } #ifdef DEBUG #ifdef NO_PRINT_LLD if(!silent) printf("\nOffset %ld Size %ld Compute delay %f\n",(long)traj_offset, (long)(*traj_size),*delay); #else if(!silent) printf("\nOffset %lld Size %lld Compute delay %f\n",(long long)traj_offset, (long long)(*traj_size),*delay); #endif #endif return(traj_offset); } /************************************************************************/ /* Open the read telemetry file and return file pointer. */ /************************************************************************/ #ifdef HAVE_ANSIC_C FILE * open_r_traj(void) #else FILE * open_r_traj() #endif { FILE *fd; fd=fopen(read_traj_filename,"r"); if(fd == (FILE *)0) { printf("Unable to open read telemetry file \"%s\"\n", read_traj_filename); exit(174); } return(fd); } /************************************************************************/ /* Open the write telemetry file and return file pointer. */ /************************************************************************/ #ifdef HAVE_ANSIC_C FILE * open_w_traj(void) #else FILE * open_w_traj() #endif { FILE *fd; fd=fopen(write_traj_filename,"r"); if(fd == (FILE *)0) { printf("Unable to open write telemetry file \"%s\"\n", write_traj_filename); exit(175); } return(fd); } /************************************************************************/ /* r_traj_size(void) */ /* This function scans the read telemetry file */ /* and establishes the number of entries */ /* and the maximum file offset. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void r_traj_size(void) #else void r_traj_size() #endif { FILE *fd; int ret; long long traj_offset = 0; long long traj_size = 0; long long max_offset = 0; int tokens; int dummy; int lines; char buf[200]; char sbuf[200]; char *ret1,*where; lines=0; fd=fopen(read_traj_filename,"r"); if(fd == (FILE *)0) { printf("Unable to open read telemetry file \"%s\"\n", read_traj_filename); exit(174); } while(1) { tokens=0; ret1=fgets(buf,200,fd); if(ret1==(char *)0) break; where=(char *)&buf[0]; strcpy(sbuf,buf); lines++; if((*where=='#') || (*where=='\n')) continue; tokens++; strtok(where," "); while( (char *)(strtok( (char *)0," ")) != (char *)0) { tokens++; } if(tokens==1) { printf("\n\tInvalid read telemetry file entry. Line %d", lines); signal_handler(); } #ifdef DEBUG printf("Tokens = %d\n",tokens); #endif if(tokens==3) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld %d\n",(long *)&traj_offset,(long *)&traj_size,&dummy); #else ret=sscanf(sbuf,"%lld %lld %d\n",(long long *)&traj_offset,(long long *)&traj_size,&dummy); #endif } if(tokens==2) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld\n",(long *)&traj_offset,(long *)&traj_size); #else ret=sscanf(sbuf,"%lld %lld\n",(long long *)&traj_offset,(long long *)&traj_size); #endif } if((tokens != 2) && (tokens !=3)) { printf("\n\tInvalid read telemetry file. Line %d\n",lines); exit(178); } if(traj_offset + traj_size > max_offset) max_offset=traj_offset + traj_size; r_traj_ops++; } r_traj_fsize=max_offset; #ifdef DEBUG #ifdef NO_PRINT_LLD printf("File size of read %ld Item count %ld\n",(long)r_traj_fsize,(long)r_traj_ops); #else printf("File size of read %lld Item count %lld\n",(long long)r_traj_fsize,(long long)r_traj_ops); #endif #endif fclose(fd); } /************************************************************************/ /* w_traj_size(void) */ /* This function scans the write telemetry file */ /* and establishes the number of entries */ /* and the maximum file offset. */ /************************************************************************/ #ifdef HAVE_ANSIC_C long long w_traj_size(void) #else long long w_traj_size() #endif { FILE *fd; int ret; long long traj_offset = 0; long long traj_size = 0; long long max_offset = 0; int dummy; int tokens,lines; char *ret1; char buf[200]; char sbuf[200]; char *where; lines=0; fd=fopen(write_traj_filename,"r"); if(fd == (FILE *)0) { printf("Unable to open write telemetry file \"%s\"\n", write_traj_filename); exit(174); } while(1) { tokens=0; ret1=fgets(buf,200,fd); if(ret1==(char *)0) break; lines++; where=(char *)&buf[0]; strcpy(sbuf,buf); if((*where=='#') || (*where=='\n')) continue; tokens++; strtok(where," "); while( (char *)(strtok( (char *)0," ")) != (char *)0) { tokens++; } if(tokens==1) { printf("\n\tInvalid write telemetry file entry. Line %d\n", lines); signal_handler(); } if(tokens==3) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld %d\n",(long *)&traj_offset,(long *)&traj_size,&dummy); #else ret=sscanf(sbuf,"%lld %lld %d",(long long *)&traj_offset,(long long *)&traj_size,&dummy); #endif } if(tokens==2) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld\n",(long *)&traj_offset,(long *)&traj_size); #else ret=sscanf(sbuf,"%lld %lld\n",(long long *)&traj_offset,(long long *)&traj_size); #endif } if(tokens > 3) { printf("\n\tInvalid write telemetry file entry. Line %d\n", lines); exit(174); } if(traj_offset + traj_size > max_offset) max_offset=traj_offset + traj_size; w_traj_ops++; } w_traj_fsize=max_offset; #ifdef DEBUG #ifdef NO_PRINT_LLD printf("File size of write %ld Item count %ld\n",(long)w_traj_fsize,(long)w_traj_ops); #else printf("File size of write %lld Item count %lld\n",(long long)w_traj_fsize,(long long)w_traj_ops); #endif #endif fclose(fd); return(max_offset); } /************************************************************************/ /* Find which version of the telemetry file format is in use. */ /************************************************************************/ #ifdef HAVE_ANSIC_C void traj_vers(void) #else void traj_vers() #endif { FILE *fd; char *where; char buf[200]; int things; char *ret1; if(r_traj_flag) { things=0; fd=fopen(read_traj_filename,"r"); if(fd == (FILE *)0) { printf("Unable to open read telemetry file \"%s\"\n", read_traj_filename); exit(174); } loop1: ret1=fgets(buf,200,fd); if(ret1==(char *)0) { fclose(fd); return; } where=(char *)&buf[0]; if((*where=='#') || (*where=='\n')) goto loop1; things++; strtok(where," "); while( (char *)(strtok( (char *)0," ")) != (char *)0) { things++; } r_traj_items=things; #ifdef DEBUG printf("Found %d items in the read telemetry file\n",things); #endif } if(w_traj_flag) { things=0; fd=fopen(write_traj_filename,"r"); if(fd == (FILE *)0) { printf("Unable to open write telemetry file \"%s\"\n", write_traj_filename); exit(174); } loop2: ret1=fgets(buf,200,fd); if(ret1==(char *)0) { fclose(fd); return; } where=(char *)&buf[0]; if((*where=='#') || (*where=='\n')) goto loop2; things++; strtok(where," "); while( (char *)(strtok( (char *)0," ")) != (char *)0) { things++; } fclose(fd); w_traj_items=things; #ifdef DEBUG printf("Found %d items in the write telemetry file\n",things); #endif } } /********************************************************************/ /* */ /* Today this initializes the default set of file sizes for Iozone. */ /* in the future it may take input from the command line or */ /* from a file. */ /* */ /********************************************************************/ #ifdef HAVE_ANSIC_C void init_file_sizes( off64_t min_f_size, off64_t max_f_size) #else void init_file_sizes(min_f_size, max_f_size) off64_t min_f_size; off64_t max_f_size; #endif { off64_t kilosi; int x; if(s_count > 1) { for(x=0; x < s_count; x++) { kilosi=s_range[x]; add_file_size((off64_t)kilosi); } } else { for(kilosi=min_f_size;kilosi<=max_f_size;kilosi*=multiplier) { add_file_size((off64_t)kilosi); } } } /********************************************************************/ /* Used to constuct the list of file sizes to test. */ /********************************************************************/ #ifdef HAVE_ANSIC_C void add_file_size(off64_t size) #else void add_file_size(size) off64_t size; #endif { struct size_entry *size_listp; struct size_entry *nsize_list; size_listp=size_list; if(size_list) { if(size_listp->next) while(size_listp->next!=0) size_listp=size_listp->next; } nsize_list=(struct size_entry *)malloc(sizeof(struct size_entry)); if(nsize_list==0) { printf("Malloc failed in add_file_size\n"); exit(180); } nsize_list->next=0; nsize_list->size=size; if(size_list == 0) size_list=nsize_list; else size_listp->next=nsize_list; size_listp=size_list; } /********************************************************************/ /* Return the next file size to test. */ /********************************************************************/ #ifdef HAVE_ANSIC_C off64_t get_next_file_size(off64_t size) #else off64_t get_next_file_size(size) off64_t size; #endif { struct size_entry *size_listp; size_listp=size_list; for( ; size_listp ; size_listp=size_listp->next ) { if(size_listp->size > size) return(size_listp->size); } return((off64_t)0); } /**********************************************************************/ /* */ /* Today this initializes the default set of record sizes for Iozone. */ /* in the future it may take input from the command line or */ /* from a file. */ /* */ /**********************************************************************/ #ifdef HAVE_ANSIC_C void init_record_sizes( off64_t min_r_size, off64_t max_r_size) #else void init_record_sizes(min_r_size, max_r_size) off64_t min_r_size; off64_t max_r_size; #endif { int x; off64_t size; if(r_count > 1) { for(x=0; x < r_count; x++) { size=r_range[x]; add_record_size((off64_t)size); } } else { for(size=min_r_size;size<=max_r_size;size*=multiplier) { add_record_size((off64_t)size); } } } #ifdef HAVE_ANSIC_C void del_record_sizes(void) #else void del_record_sizes() #endif { struct size_entry *size_listp; struct size_entry *save_item; size_listp=rec_size_list; if(rec_size_list) { while(size_listp!=0) { save_item=size_listp->next; free(size_listp); size_listp=save_item; } } rec_size_list=0; } /********************************************************************/ /* Used to constuct the list of record sizes to test. */ /********************************************************************/ #ifdef HAVE_ANSIC_C void add_record_size(off64_t size) #else void add_record_size(size) off64_t size; #endif { struct size_entry *size_listp; struct size_entry *nsize_list; size_listp=rec_size_list; if(rec_size_list) { if(size_listp->next) while(size_listp->next!=0) size_listp=size_listp->next; } nsize_list=(struct size_entry *)malloc(sizeof(struct size_entry)); if(nsize_list==0) { printf("Malloc failed in add_file_size\n"); exit(180); } nsize_list->next=0; nsize_list->size=size; if(rec_size_list == 0) rec_size_list=nsize_list; else size_listp->next=nsize_list; size_listp=rec_size_list; } /********************************************************************/ /* Return the next record size to test. */ /********************************************************************/ #ifdef HAVE_ANSIC_C off64_t get_next_record_size(off64_t size) #else off64_t get_next_record_size(size) off64_t size; #endif { struct size_entry *size_listp; size_listp=rec_size_list; for( ; size_listp ; size_listp=size_listp->next ) { if(size_listp->size > size) return(size_listp->size); } return((off64_t)0); } /* * Socket based communication mechanism. * It's intended use is to be the communication mechanism * that will be used to get Iozone to run across * multiple clients. 1/11/2002 Don Capps * The communication model permits a master to send and receive * messages to and from clients, and for clients to be able to * send and receive messages to and from the master. */ /* * Interfaces are: Master: int start_master_listen(void) Called to create masters listening port. void master_listen(int sock, int size_of_message) Call when master wants to block and read a message. int start_master_send(char *child_host_name, int port) Call to start a send channel to a client. void master_send(int child_socket_val, char *host_name, char *send_buffer, int send_size) Call to send message to a client. void stop_master_listen(int master_socket_val) Call to release the masters listening port. void stop_master_send(int child_socket_val) Call to release the masters send port to a client. Clients: int start_child_listen(int size_of_message) Called to create clients listening port. void child_listen(int sock, int size_of_message) Call when client wants to block and read a message from the master. void child_send(int child_socket_val, char *controlling_host_name, char *send_buffer, int send_size) Call to send message to the master. void stop_child_listen(int child_socket_val) Call to release the clients listening port. void stop_child_send(int child_socket_val) Call to release the clients send port to the master. Messages are sent in command blocks. The structure is client_command for messages from the master to the client, and master_command for messages sent from a client to the master. */ /* * Allocate the master listening port that * all children will use to send messages to the master. */ #ifdef HAVE_ANSIC_C int start_master_listen(void) #else int start_master_listen() #endif { int s; int rc; int tmp_port; int sockerr; struct sockaddr_in addr; int recv_buf_size=65536*4; int optval=1; struct linger dummy={1,0}; s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("socket failed:"); exit(19); } sockerr = setsockopt (s, SOL_SOCKET, SO_RCVBUF, (char *) &recv_buf_size, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 1\n"); } sockerr = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 2\n"); } sockerr = setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &dummy, sizeof(struct linger)); if ( sockerr == -1 ) { perror("Error in setsockopt 2\n"); } tmp_port=HOST_LIST_PORT; bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_port = htons(tmp_port); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; addr.sin_port=htons(tmp_port); continue; } master_listen_port = ntohs(addr.sin_port); } if(rc < 0) { perror("bind failed\n"); exit(20); } if(mdebug) printf("Master listening on socket %d Port %d\n",s,tmp_port); return(s); } /* * Master listens for messages and blocks until * something arrives. */ struct sockaddr_in listener_sync_sock; #ifdef HAVE_ANSIC_C void master_listen(int sock, int size_of_message) #else void master_listen(sock, size_of_message) int sock, size_of_message; #endif { int tsize; int s; struct sockaddr_in *addr; unsigned int me; int ns,ret; struct master_neutral_command *mnc; mnc=(struct master_neutral_command *)&master_rcv_buf[0]; tsize = size_of_message; addr=&listener_sync_sock; s = sock; me=sizeof(struct sockaddr_in); if(mdebug) printf("Master in listening mode on socket %d\n",s); again: ret=listen(s,MAXSTREAMS); if(ret != 0) { perror("Master: listen returned error\n"); } if(mdebug) printf("Master in accepting connection\n"); #if defined(ANDROID) ns=accept((int)s,(struct sockaddr *)addr,(socklen_t *)&me); #else ns=accept(s,(void *)addr,&me); #endif if(ns < 0) { printf("Master socket %d\n",s); perror("Master: ***** accept returned error *****\n"); sleep(1); goto again; } if(mdebug) printf("Master in reading from connection\n"); ret=read(ns,mnc,tsize); if(ret < tsize) { printf("Master read failed. Ret %d Errno %d\n",ret,errno); } close(ns); } /* * Child sends message to master. */ #ifdef HAVE_ANSIC_C void child_send(char *controlling_host_name, struct master_command *send_buffer, int send_size) #else void child_send(controlling_host_name, send_buffer, send_size) char *controlling_host_name; struct master_command *send_buffer; int send_size; #endif { int rc,child_socket_val; struct hostent *he; int tmp_port; struct in_addr *ip; struct sockaddr_in cs_addr,cs_raddr; struct master_neutral_command outbuf; struct timespec req,rem; req.tv_sec = 0; req.tv_nsec = 10000000; rem.tv_sec = 0; rem.tv_nsec = 10000000; if(cdebug) { fprintf(newstdout,"Start_child_send: %s Size %d\n",controlling_host_name,send_size); fflush(newstdout); } he = gethostbyname(controlling_host_name); if (he == NULL) { exit(22); } ip = (struct in_addr *)he->h_addr_list[0]; over: cs_raddr.sin_family = AF_INET; cs_raddr.sin_port = htons(controlling_host_port); cs_raddr.sin_addr.s_addr = ip->s_addr; child_socket_val = socket(AF_INET, SOCK_STREAM, 0); if (child_socket_val < 0) { perror("Child: socket failed:"); exit(23); } bzero(&cs_addr, sizeof(struct sockaddr_in)); tmp_port= CHILD_ESEND_PORT; cs_addr.sin_port = htons(tmp_port); cs_addr.sin_family = AF_INET; cs_addr.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(child_socket_val, (struct sockaddr *)&cs_addr, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; cs_addr.sin_port=htons(tmp_port); continue; } } if (rc < 0) { perror("Child: bind failed\n"); exit(24); } if(cdebug) { fprintf(newstdout,"Child sender bound to port %d Master port %d \n",tmp_port,HOST_LIST_PORT); fflush(newstdout); } again: nanosleep(&req,&rem); rc = connect(child_socket_val, (struct sockaddr *)&cs_raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if((ecount++ < 200) && (errno != EISCONN)) { nanosleep(&req,&rem); /*sleep(1);*/ goto again; } if(cdebug) { fprintf(newstdout,"Child: connect failed. Errno %d \n",errno); fflush(newstdout); } close(child_socket_val); nanosleep(&req,&rem); /*sleep(1);*/ ecount=0; goto over; } ecount=0; if(cdebug) { fprintf(newstdout,"Child connected\n"); fflush(newstdout); } /* NOW send */ bzero(&outbuf, sizeof(struct master_neutral_command)); if(cdebug>=1) { fprintf(newstdout,"Child %d sending message to %s \n",(int)chid, controlling_host_name); fflush(newstdout); } /* * Convert internal commands to string format to neutral format for portability */ strcpy(outbuf.m_host_name,send_buffer->m_host_name); strcpy(outbuf.m_client_name,send_buffer->m_client_name); sprintf(outbuf.m_client_number,"%d",send_buffer->m_client_number); sprintf(outbuf.m_client_error,"%d",send_buffer->m_client_error); sprintf(outbuf.m_child_port,"%d",send_buffer->m_child_port); sprintf(outbuf.m_child_async_port,"%d",send_buffer->m_child_async_port); sprintf(outbuf.m_command,"%d",send_buffer->m_command); sprintf(outbuf.m_testnum,"%d",send_buffer->m_testnum); sprintf(outbuf.m_version,"%d",send_buffer->m_version); sprintf(outbuf.m_mygen,"%d",send_buffer->m_mygen); sprintf(outbuf.m_throughput,"%f",send_buffer->m_throughput); sprintf(outbuf.m_cputime,"%f", send_buffer->m_cputime); sprintf(outbuf.m_walltime,"%f",send_buffer->m_walltime); sprintf(outbuf.m_stop_flag,"%d",send_buffer->m_stop_flag); sprintf(outbuf.m_actual,"%f",send_buffer->m_actual); #ifdef NO_PRINT_LLD sprintf(outbuf.m_child_flag,"%ld",(long)(send_buffer->m_child_flag)); #else sprintf(outbuf.m_child_flag,"%lld",(long long)(send_buffer->m_child_flag)); #endif rc=write(child_socket_val,&outbuf,sizeof(struct master_neutral_command)); if (rc < 0) { perror("write failed\n"); exit(26); } close(child_socket_val); } /* * Master sending message to a child * There should be a unique child_socket_val for each * child. */ #ifdef HAVE_ANSIC_C void master_send(int child_socket_val, char *host_name, struct client_command *send_buffer, int send_size) #else void master_send(child_socket_val, host_name, send_buffer, send_size) int child_socket_val; char *host_name; struct client_command *send_buffer; int send_size; #endif { int rc; struct client_neutral_command outbuf; bzero(&outbuf,sizeof(struct client_neutral_command)); if(mdebug) { printf("Master_neutral_command size = %lu\n",(unsigned long)sizeof(struct master_neutral_command)); printf("Client_neutral_command size = %lu\n",(unsigned long)sizeof(struct client_neutral_command)); } /* * Convert internal commands to string format for neutral format/portability */ strcpy(outbuf.c_host_name,send_buffer->c_host_name); strcpy(outbuf.c_pit_hostname,send_buffer->c_pit_hostname); strcpy(outbuf.c_pit_service,send_buffer->c_pit_service); strcpy(outbuf.c_client_name,send_buffer->c_client_name); strcpy(outbuf.c_working_dir,send_buffer->c_working_dir); strcpy(outbuf.c_file_name,send_buffer->c_file_name); strcpy(outbuf.c_path_dir,send_buffer->c_path_dir); strcpy(outbuf.c_execute_name,send_buffer->c_execute_name); strcpy(outbuf.c_write_traj_filename,send_buffer->c_write_traj_filename); strcpy(outbuf.c_read_traj_filename,send_buffer->c_read_traj_filename); sprintf(outbuf.c_oflag,"%d",send_buffer->c_oflag); sprintf(outbuf.c_mfflag,"%d",send_buffer->c_mfflag); sprintf(outbuf.c_unbuffered,"%d",send_buffer->c_unbuffered); sprintf(outbuf.c_noretest,"%d",send_buffer->c_noretest); sprintf(outbuf.c_notruncate,"%d",send_buffer->c_notruncate); sprintf(outbuf.c_read_sync,"%d",send_buffer->c_read_sync); sprintf(outbuf.c_jflag,"%d",send_buffer->c_jflag); sprintf(outbuf.c_async_flag,"%d",send_buffer->c_async_flag); sprintf(outbuf.c_mmapflag,"%d",send_buffer->c_mmapflag); sprintf(outbuf.c_k_flag,"%d",send_buffer->c_k_flag); sprintf(outbuf.c_h_flag,"%d",send_buffer->c_h_flag); sprintf(outbuf.c_mflag,"%d",send_buffer->c_mflag); sprintf(outbuf.c_pflag,"%d",send_buffer->c_pflag); sprintf(outbuf.c_stride_flag,"%d",send_buffer->c_stride_flag); sprintf(outbuf.c_verify,"%d",send_buffer->c_verify); sprintf(outbuf.c_sverify,"%d",send_buffer->c_sverify); sprintf(outbuf.c_odsync,"%d",send_buffer->c_odsync); sprintf(outbuf.c_diag_v,"%d",send_buffer->c_diag_v); sprintf(outbuf.c_zero_pct,"%d",send_buffer->c_zero_pct); sprintf(outbuf.c_N_special,"%d",send_buffer->c_N_special); sprintf(outbuf.c_dedup_granule_size,"%d",send_buffer->c_dedup_granule_size); sprintf(outbuf.c_dedup,"%d",send_buffer->c_dedup); sprintf(outbuf.c_dedup_flag,"%d",send_buffer->c_dedup_flag); sprintf(outbuf.c_dedup_iflag,"%d",send_buffer->c_dedup_iflag); sprintf(outbuf.c_dedup_bflag,"%d",send_buffer->c_dedup_bflag); sprintf(outbuf.c_dedup_interior,"%d",send_buffer->c_dedup_interior); sprintf(outbuf.c_dedup_compress,"%d",send_buffer->c_dedup_compress); sprintf(outbuf.c_dedup_mseed,"%d",send_buffer->c_dedup_mseed); sprintf(outbuf.c_chid_skew,"%d",send_buffer->c_chid_skew); sprintf(outbuf.c_hist_summary,"%d",send_buffer->c_hist_summary); sprintf(outbuf.c_op_rate,"%d",send_buffer->c_op_rate); sprintf(outbuf.c_op_rate_flag,"%d",send_buffer->c_op_rate_flag); sprintf(outbuf.c_Q_flag,"%d",send_buffer->c_Q_flag); sprintf(outbuf.c_inc_think,"%d",send_buffer->c_inc_think); sprintf(outbuf.c_L_flag,"%d",send_buffer->c_L_flag); sprintf(outbuf.c_include_flush,"%d",send_buffer->c_include_flush); sprintf(outbuf.c_OPS_flag,"%d",send_buffer->c_OPS_flag); sprintf(outbuf.c_mmapnsflag,"%d",send_buffer->c_mmapnsflag); sprintf(outbuf.c_mmapssflag,"%d",send_buffer->c_mmapssflag); sprintf(outbuf.c_mmapasflag,"%d",send_buffer->c_mmapasflag); sprintf(outbuf.c_no_copy_flag,"%d",send_buffer->c_no_copy_flag); sprintf(outbuf.c_include_close,"%d",send_buffer->c_include_close); sprintf(outbuf.c_disrupt_flag,"%d",send_buffer->c_disrupt_flag); sprintf(outbuf.c_compute_flag,"%d",send_buffer->c_compute_flag); sprintf(outbuf.c_xflag,"%d",send_buffer->c_xflag); sprintf(outbuf.c_MS_flag,"%d",send_buffer->c_MS_flag); sprintf(outbuf.c_mmap_mix,"%d",send_buffer->c_mmap_mix); sprintf(outbuf.c_Kplus_flag,"%d",send_buffer->c_Kplus_flag); sprintf(outbuf.c_w_traj_flag,"%d",send_buffer->c_w_traj_flag); sprintf(outbuf.c_r_traj_flag,"%d",send_buffer->c_r_traj_flag); sprintf(outbuf.c_direct_flag,"%d",send_buffer->c_direct_flag); sprintf(outbuf.c_cpuutilflag,"%d",send_buffer->c_cpuutilflag); sprintf(outbuf.c_seq_mix,"%d",send_buffer->c_seq_mix); sprintf(outbuf.c_del_flag,"%d",send_buffer->c_del_flag); sprintf(outbuf.c_client_number,"%d",send_buffer->c_client_number); sprintf(outbuf.c_command,"%d",send_buffer->c_command); sprintf(outbuf.c_testnum,"%d",send_buffer->c_testnum); sprintf(outbuf.c_no_unlink,"%d",send_buffer->c_no_unlink); sprintf(outbuf.c_no_write,"%d",send_buffer->c_no_write); sprintf(outbuf.c_file_lock,"%d",send_buffer->c_file_lock); sprintf(outbuf.c_rec_lock,"%d",send_buffer->c_rec_lock); sprintf(outbuf.c_Kplus_readers,"%d",send_buffer->c_Kplus_readers); sprintf(outbuf.c_multiplier,"%d",send_buffer->c_multiplier); sprintf(outbuf.c_share_file,"%d",send_buffer->c_share_file); sprintf(outbuf.c_pattern,"%d",send_buffer->c_pattern); sprintf(outbuf.c_version,"%d",send_buffer->c_version); sprintf(outbuf.c_base_time,"%d",send_buffer->c_base_time); sprintf(outbuf.c_num_child,"%d",send_buffer->c_num_child); sprintf(outbuf.c_pct_read,"%d",send_buffer->c_pct_read); sprintf(outbuf.c_advise_op,"%d",send_buffer->c_advise_op); sprintf(outbuf.c_advise_flag,"%d",send_buffer->c_advise_flag); sprintf(outbuf.c_restf,"%d",send_buffer->c_restf); sprintf(outbuf.c_mygen,"%d",send_buffer->c_mygen); #ifdef NO_PRINT_LLD sprintf(outbuf.c_stride,"%ld"(long)(,send_buffer->c_stride)); sprintf(outbuf.c_rest_val,"%ld",(long)(send_buffer->c_rest_val)); sprintf(outbuf.c_delay,"%ld",(long)(send_buffer->c_delay)); sprintf(outbuf.c_purge,"%ld",(long)(send_buffer->c_purge)); sprintf(outbuf.c_fetchon,"%ld",(long)(send_buffer->c_fetchon)); sprintf(outbuf.c_numrecs64,"%ld",(long)(send_buffer->c_numrecs64)); sprintf(outbuf.c_reclen,"%ld",(long)(send_buffer->c_reclen)); sprintf(outbuf.c_child_flag,"%ld",(long)(send_buffer->c_child_flag)); sprintf(outbuf.c_delay_start,"%ld",(long)(send_buffer->c_delay_start)); sprintf(outbuf.c_depth,"%ld",(long)(send_buffer->c_depth)); #else sprintf(outbuf.c_delay,"%lld",(long long)(send_buffer->c_delay)); sprintf(outbuf.c_stride,"%lld",(long long)(send_buffer->c_stride)); sprintf(outbuf.c_rest_val,"%lld",(long long)(send_buffer->c_rest_val)); sprintf(outbuf.c_purge,"%lld",(long long)(send_buffer->c_purge)); sprintf(outbuf.c_fetchon,"%lld",(long long)(send_buffer->c_fetchon)); sprintf(outbuf.c_numrecs64,"%lld",(long long)(send_buffer->c_numrecs64)); sprintf(outbuf.c_reclen,"%lld",(long long)(send_buffer->c_reclen)); sprintf(outbuf.c_child_flag,"%lld",(long long)(send_buffer->c_child_flag)); sprintf(outbuf.c_delay_start,"%lld",(long long)(send_buffer->c_delay_start)); sprintf(outbuf.c_depth,"%lld",(long long)(send_buffer->c_depth)); #endif sprintf(outbuf.c_stop_flag,"%d",send_buffer->c_stop_flag); sprintf(outbuf.c_compute_time,"%f",send_buffer->c_compute_time); if(mdebug >= 1) printf("Master sending message to %s \n",host_name); /*rc = send(child_socket_val, (char *)&outbuf, sizeof(struct client_neutral_command), 0);*/ rc = write(child_socket_val, (char *)&outbuf, sizeof(struct client_neutral_command)); if (rc < 0) { perror("write failed\n"); exit(26); } } /* * Close the childs listening port for messages from the master. */ #ifdef HAVE_ANSIC_C void stop_child_listen(int child_socket_val) #else void stop_child_listen(child_socket_val) int child_socket_val; #endif { close(child_socket_val); } /* * Close the childs channel for sending messages to the master. */ #ifdef HAVE_ANSIC_C void O_stop_child_send(int child_socket_val) #else void O_stop_child_send(child_socket_val) int child_socket_val; #endif { close(child_socket_val); } /* * Close the masters listening channel for all clients messages. */ #ifdef HAVE_ANSIC_C void stop_master_listen(int master_socket_val) #else void stop_master_listen(master_socket_val) int master_socket_val; #endif { if(mdebug) printf("Stop master listen\n"); /* shutdown(master_socket_val,SHUT_RDWR); */ close(master_socket_val); master_socket_val = 0; } /* * Close the masters send channel a particular child. */ #ifdef HAVE_ANSIC_C void stop_master_send(int child_socket_val) #else void stop_master_send(child_socket_val) int child_socket_val; #endif { close(child_socket_val); } /* * Start the childs listening service for messages from the master. */ #ifdef HAVE_ANSIC_C int start_child_listen(int size_of_message) #else int start_child_listen(size_of_message) int size_of_message; #endif { int tsize; int s; int rc; int xx; int tmp_port; int sockerr; int recv_buf_size=65536; int optval=1; struct linger dummy={1,0}; xx = 0; tsize=size_of_message; /* Number of messages to receive */ s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("socket failed:"); exit(19); } sockerr = setsockopt (s, SOL_SOCKET, SO_RCVBUF, (char *) &recv_buf_size, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 3\n"); } sockerr = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 4\n"); } sockerr = setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &dummy, sizeof(struct linger)); if ( sockerr == -1 ) { perror("Error in setsockopt 4\n"); } bzero(&child_sync_sock, sizeof(struct sockaddr_in)); tmp_port=CHILD_LIST_PORT+chid; child_sync_sock.sin_port = htons(tmp_port); child_sync_sock.sin_family = AF_INET; child_sync_sock.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(s, (struct sockaddr *)&child_sync_sock, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; child_sync_sock.sin_port=htons(tmp_port); continue; } } child_port = ntohs(child_sync_sock.sin_port); if(cdebug ==1) { fprintf(newstdout,"Child %d: Listen: Bound at port %d\n",(int)chid, tmp_port); fflush(newstdout); } if(rc < 0) { fprintf(newstdout,"Child bind failed. Errno %d\n",errno); fflush(newstdout); exit(20); } return(s); } #ifdef HAVE_ANSIC_C int child_attach(int s, int flag) #else int child_attach(s, flag) int s,flag; #endif { unsigned int me; int ns; struct sockaddr_in *addr; if(flag) { addr=&child_async_sock; if(cdebug) { fprintf(newstdout,"Child %d attach async\n",(int)chid); fflush(newstdout); } } else { addr=&child_sync_sock; if(cdebug) { fprintf(newstdout,"Child %d attach sync\n",(int)chid); fflush(newstdout); } } me=sizeof(struct sockaddr_in); if(cdebug) { printf("Child %d enters listen\n",(int)chid); fflush(stdout); } listen(s,10); if(cdebug) { fprintf(newstdout,"Child %d enters accept\n",(int)chid); fflush(newstdout); } #if defined(ANDROID) ns=accept((int)s,(struct sockaddr *)addr,(socklen_t *)&me); #else ns=accept(s,(void *)addr,&me); #endif if(cdebug) { fprintf(newstdout,"Child %d attached for receive. Sock %d %d\n", (int)chid, ns,errno); fflush(newstdout); } return(ns); } /* * The clients use this to block waiting for a message from * the master. */ #ifdef HAVE_ANSIC_C void child_listen(int sock, int size_of_message) #else void child_listen(sock, size_of_message) int sock, size_of_message; #endif { int tsize; int rcvd; int s; int rc; char *cnc; cnc = (char *)&child_rcv_buf[0]; bzero(cnc, sizeof(child_rcv_buf)); s = sock; tsize=size_of_message; /* Number of messages to receive */ rcvd = 0; while(rcvd < tsize) { if(cdebug ==1) { fprintf(newstdout,"Child %d In recieve \n",(int)chid); fflush(newstdout); } rc=read(s,cnc,size_of_message); if(rc < 0) { fprintf(newstdout,"Read failed. Errno %d \n",errno); fflush(newstdout); exit(21); } if(cdebug >= 1) { fprintf(newstdout,"Child %d: Got %d bytes\n",(int)chid, rc); fflush(newstdout); } rcvd+=rc; cnc+=rc; } if(cdebug >= 1) { fprintf(newstdout,"Child %d: return from listen\n",(int)chid); fflush(newstdout); } } /* * Start the childs async listening service for messages from the master. */ #ifdef HAVE_ANSIC_C int start_child_listen_async(int size_of_message) #else int start_child_listen_async(size_of_message) int size_of_message; #endif { int tsize; int s; int rc; int xx; int tmp_port; int sockerr; int recv_buf_size=65536; int optval=1; xx = 0; tsize=size_of_message; /* Number of messages to receive */ s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("socket failed:"); exit(19); } sockerr = setsockopt (s, SOL_SOCKET, SO_RCVBUF, (char *) &recv_buf_size, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 5\n"); } sockerr = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 6\n"); } bzero(&child_async_sock, sizeof(struct sockaddr_in)); tmp_port=CHILD_ALIST_PORT; child_async_sock.sin_port = htons(tmp_port); child_async_sock.sin_family = AF_INET; child_async_sock.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(s, (struct sockaddr *)&child_async_sock, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; child_async_sock.sin_port=htons(tmp_port); continue; } } child_async_port = ntohs(child_async_sock.sin_port); if(cdebug ==1) { fprintf(newstdout,"Child %d: Async Listen: Bound at port %d\n", (int)chid,tmp_port); fflush(newstdout); } if(rc < 0) { fprintf(newstdout,"bind failed. Errno %d \n",errno); fflush(newstdout); exit(20); } return(s); } /* * The clients use this to block waiting for an async message from * the master. */ #ifdef HAVE_ANSIC_C void child_listen_async(int sock, int size_of_message) #else void child_listen_async(sock, size_of_message) int sock, size_of_message; #endif { int tsize; int rcvd; int s; int rc; char *cnc; cnc = &child_async_rcv_buf[0]; s = sock; tsize=size_of_message; /* Number of messages to receive */ rcvd = 0; while(rcvd < tsize) { if(cdebug ==1) { fprintf(newstdout,"Child %d In async recieve \n",(int)chid); fflush(newstdout); } rc=read(s,cnc,size_of_message); if(rc < 0) { fprintf(newstdout,"Read failed. Errno %d \n",errno); fflush(newstdout); exit(21); } /* Special case. If master gets final results, it can exit, and close the connection to the async child too quickly. When this happens the child gets a read() that returns 0. It just needs to exit here. */ if(rc==0) exit(0); if(cdebug >= 1) { fprintf(newstdout,"Child %d: Got %d bytes (async) \n",(int)chid,rc); fflush(newstdout); } rcvd+=rc; cnc+=rc; } if(cdebug >= 1) { fprintf(newstdout,"Child %d: return from async listen\n",(int)chid); fflush(newstdout); } } /* * Start the channel for the master to send a message to * a particular child on a particular port that the child * has created for the parent to use to communicate. */ #ifdef HAVE_ANSIC_C int start_master_send(char *child_host_name, int child_port, struct in_addr *my_s_addr) #else int start_master_send(child_host_name, child_port, my_s_addr) char *child_host_name; int child_port; struct in_addr *my_s_addr; #endif { int rc,master_socket_val; struct sockaddr_in addr,raddr; struct hostent *he; int port,tmp_port; int ecount = 0; struct in_addr *ip; struct timespec req,rem; req.tv_sec = 0; req.tv_nsec = 10000000; rem.tv_sec = 0; rem.tv_nsec = 10000000; he = gethostbyname(child_host_name); if (he == NULL) { printf("Master: Bad hostname >%s<\n",child_host_name); fflush(stdout); exit(22); } if(mdebug ==1) { printf("Master: start master send: %s\n", he->h_name); fflush(stdout); } ip = (struct in_addr *)he->h_addr_list[0]; #ifndef UWIN if(mdebug ==1) { printf("Master: child name: %s\n", (char *)inet_ntoa(*ip)); printf("Master: child Port: %d\n", child_port); fflush(stdout); } #endif port=child_port; my_s_addr->s_addr = ip->s_addr; /*port=CHILD_LIST_PORT;*/ raddr.sin_family = AF_INET; raddr.sin_port = htons(port); raddr.sin_addr.s_addr = ip->s_addr; master_socket_val = socket(AF_INET, SOCK_STREAM, 0); if (master_socket_val < 0) { perror("Master: socket failed:"); exit(23); } bzero(&addr, sizeof(struct sockaddr_in)); tmp_port=HOST_ESEND_PORT; addr.sin_port = htons(tmp_port); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(master_socket_val, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; addr.sin_port=htons(tmp_port); continue; } } if(mdebug ==1) { printf("Master: Bound port\n"); fflush(stdout); } if (rc < 0) { perror("Master: bind failed for sync channel to child.\n"); exit(24); } nanosleep(&req,&rem); again: rc = connect(master_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++ < 300) { nanosleep(&req,&rem); /*sleep(1);*/ goto again; } perror("Master: connect failed\n"); printf("Error %d\n",errno); exit(25); } if(mdebug ==1) { printf("Master Connected\n"); fflush(stdout); } return (master_socket_val); } /* * Start the channel for the master to send a message to * a particular child on a particular port that the child * has created for the parent to use to communicate. */ #ifdef HAVE_ANSIC_C int start_master_send_async(char *child_host_name, int child_port, struct in_addr my_s_addr) #else int start_master_send_async(child_host_name, child_port, my_s_addr) char *child_host_name; int child_port; struct in_addr my_s_addr; #endif { int rc,master_socket_val; struct sockaddr_in addr,raddr; int port,tmp_port; int ecount = 0; struct timespec req,rem; req.tv_sec = 0; req.tv_nsec = 10000000; rem.tv_sec = 0; rem.tv_nsec = 10000000; port=child_port; nanosleep(&req,&rem); over: raddr.sin_family = AF_INET; raddr.sin_port = htons(port); raddr.sin_addr.s_addr = my_s_addr.s_addr; master_socket_val = socket(AF_INET, SOCK_STREAM, 0); if (master_socket_val < 0) { perror("Master: async socket failed:"); exit(23); } bzero(&addr, sizeof(struct sockaddr_in)); tmp_port=HOST_ASEND_PORT; addr.sin_port = htons(tmp_port); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(master_socket_val, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; addr.sin_port=htons(tmp_port); continue; } } if(mdebug ==1) { printf("Master: Bound async port\n"); fflush(stdout); } if (rc < 0) { perror("Master: bind async failed\n"); exit(24); } again: rc = connect(master_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++ < 300) { /* Really need this sleep for Windows */ #if defined (Windows) sleep(1); #else nanosleep(&req,&rem); #endif goto again; } perror("Master: async connect failed\n"); close(master_socket_val); #if defined (Windows) sleep(1); #else nanosleep(&req,&rem); #endif /*sleep(1);*/ ecount=0; goto over; } if(mdebug ==1) { printf("Master async Connected\n"); fflush(stdout); } return (master_socket_val); } /* * If not "distributed" then call fork. The "distributed" * will start iozone on a remote node. */ #ifdef HAVE_ANSIC_C long long start_child_proc(int testnum,long long numrecs64, long long reclen) #else long long start_child_proc(testnum, numrecs64, reclen) int testnum; long long numrecs64, reclen; #endif { long long x; if(distributed && master_iozone) { x=(long long)pick_client(testnum,numrecs64, reclen); } else { x=(long long)fork(); } if(mdebug) printf("Starting proc %d\n",(int)x); return(x); } /* * This function picks a client from the list of clients and * starts it running on the remote machine. It also waits for * the remote process to join and then sends the client * the state information it needs to begin to run the * test. The client will initialize its state space, * begin the test and block as the barrier waiting * for the master to say go. */ #ifdef HAVE_ANSIC_C int pick_client(int testnum,long long numrecs64, long long reclen) #else int pick_client(testnum, numrecs64, reclen) int testnum; long long numrecs64, reclen; #endif { int x; int c_command,child_index; struct client_command cc; struct master_command mc; struct master_neutral_command *mnc; char command[512]; struct in_addr my_s_addr; char my_port_num[12]; bzero(&cc,sizeof(struct client_command)); for(x=0;x<512;x++) command[x]=0; current_client_number++; /* Need to start with 1 */ x=current_client_number; child_idents[x-1].state = C_STATE_ZERO; /* Step 1. Now start client going on remote node. */ find_remote_shell(remote_shell); sprintf(command,"%s ",remote_shell); strcat(command,child_idents[x-1].child_name); strcat(command," -n '"); strcat(command,child_idents[x-1].execute_path); strcat(command," -+s -t 1 -r 4 -s 4 -+c "); strcat(command,controlling_host_name); if (master_listen_port != HOST_LIST_PORT) { sprintf(my_port_num," -+i %d",master_listen_port); strcat(command,my_port_num); } strcat(command," '"); usleep(100000); /* Don't spawn rsh too fast... */ junk=system(command); /* system("remsh rsnperf '/home/capps/niozone/iozone -+s -t 1 -r 4 -s 8 -+c rsnperf'"); */ if(mdebug) printf("%s",command); /* Format example: */ /* */ /* system("remsh rsnperf '/home/capps/niozone/iozone */ /* -+s -t 1 -r 4 -s 8 -+c rsnperf'"); */ /* */ /* Step 2. Wait for join from new client. */ child_idents[x-1].state = C_STATE_WAIT_WHO; if(mdebug>=1) printf("\nMaster listening for child to send join message.\n"); master_listen(master_listen_socket,sizeof(struct master_neutral_command)); mnc = (struct master_neutral_command *)&master_rcv_buf[0]; /* * Convert from string format back to internal representation */ sscanf(mnc->m_child_port,"%d",&mc.m_child_port); sscanf(mnc->m_child_async_port,"%d",&mc.m_child_async_port); sscanf(mnc->m_command,"%d",&mc.m_command); sscanf(mnc->m_version,"%d",&mc.m_version); if(mc.m_version != proto_version) { printf("Client > %s < is not running the same version of Iozone !! C%d M%d\n", child_idents[x-1].child_name, mc.m_version, proto_version); } c_port = mc.m_child_port; a_port = mc.m_child_async_port; c_command = mc.m_command; if(mdebug>=1) { printf("Master back from listen child Joined.\n"); printf("Master: Command %d\n",c_command); } /* Step 3. Then start_master_send() for this client. */ if(mdebug>=1) printf("Starting master send channel\n"); master_send_sockets[x-1]= start_master_send(child_idents[x-1].child_name,c_port, &my_s_addr); if(mdebug>=1) printf("Starting master send async channel\n"); master_send_async_sockets[x-1]= start_master_send_async(child_idents[x-1].child_name,a_port, my_s_addr); child_idents[x-1].master_socket_num = master_send_sockets[x-1]; child_idents[x-1].master_async_socket_num = master_send_async_sockets[x-1]; child_idents[x-1].child_number = x-1; child_idents[x-1].child_port = c_port; child_idents[x-1].child_async_port = a_port; /* */ /* Step 4. Send message to client telling him his name, number, */ /* rsize, fsize, and test to run. */ strcpy(cc.c_host_name ,controlling_host_name); strcpy(cc.c_pit_hostname ,pit_hostname); strcpy(cc.c_pit_service ,pit_service); strcpy(cc.c_client_name ,child_idents[x-1].child_name); strcpy(cc.c_working_dir ,child_idents[x-1].workdir); strcpy(cc.c_file_name ,child_idents[x-1].file_name); strcpy(cc.c_write_traj_filename ,write_traj_filename); strcpy(cc.c_read_traj_filename ,read_traj_filename); cc.c_command = R_JOIN_ACK; cc.c_client_number = x-1; cc.c_testnum = testnum; cc.c_numrecs64 = numrecs64; cc.c_reclen = reclen; cc.c_oflag = oflag; cc.c_mfflag = mfflag; cc.c_unbuffered = unbuffered; cc.c_noretest = noretest; cc.c_notruncate = notruncate; cc.c_read_sync = read_sync; cc.c_jflag = jflag; cc.c_direct_flag = direct_flag; cc.c_cpuutilflag = cpuutilflag; cc.c_seq_mix = seq_mix; cc.c_del_flag = del_flag; cc.c_async_flag = async_flag; cc.c_k_flag = k_flag; cc.c_h_flag = h_flag; cc.c_mflag = mflag; cc.c_pflag = pflag; cc.c_stride_flag = stride_flag; cc.c_fetchon = fetchon; cc.c_verify = verify; cc.c_sverify = sverify; cc.c_odsync = odsync; cc.c_diag_v = diag_v; cc.c_zero_pct = zero_pct; cc.c_N_special = N_special; cc.c_dedup_granule_size = dedup_granule_size; cc.c_dedup_flag = dedup_flag; cc.c_dedup_iflag = dedup_iflag; cc.c_dedup_bflag = dedup_bflag; cc.c_dedup = dedup; cc.c_dedup_interior = dedup_interior; cc.c_dedup_compress = dedup_compress; cc.c_dedup_mseed = dedup_mseed; cc.c_chid_skew = chid_skew; cc.c_hist_summary = hist_summary; cc.c_op_rate = op_rate; cc.c_op_rate_flag = op_rate_flag; cc.c_file_lock = file_lock; cc.c_rec_lock = rlocking; cc.c_Kplus_readers = Kplus_readers; cc.c_multiplier = multiplier; cc.c_share_file = share_file; cc.c_pattern = pattern; cc.c_version = proto_version; cc.c_base_time = base_time; cc.c_num_child = (int)num_child; cc.c_pct_read = pct_read; cc.c_advise_op = advise_op; cc.c_advise_flag = advise_flag; cc.c_restf = restf; cc.c_mygen = mygen; cc.c_Q_flag = Q_flag; cc.c_inc_think = inc_think; cc.c_L_flag = L_flag; cc.c_xflag = xflag; cc.c_w_traj_flag = w_traj_flag; cc.c_r_traj_flag = r_traj_flag; cc.c_include_flush = include_flush; cc.c_OPS_flag = OPS_flag; cc.c_purge = purge; cc.c_mmapflag = mmapflag; cc.c_mmapasflag = mmapasflag; cc.c_mmapnsflag = mmapnsflag; cc.c_mmapssflag = mmapssflag; cc.c_no_copy_flag = no_copy_flag; cc.c_no_unlink = no_unlink; cc.c_no_write = no_write; cc.c_include_close = include_close; cc.c_disrupt_flag = disrupt_flag; cc.c_compute_flag = compute_flag; cc.c_delay = delay; cc.c_stride = stride; cc.c_rest_val = rest_val; cc.c_delay_start = delay_start; cc.c_compute_time = compute_time; cc.c_depth = depth; cc.c_MS_flag = MS_flag; cc.c_mmap_mix = mmap_mix; cc.c_Kplus_flag = Kplus_flag; if(mdebug) printf("Master sending client who he is\n"); master_send(master_send_sockets[x-1],cc.c_client_name, &cc,sizeof(struct client_command)); child_idents[x-1].state = C_STATE_WAIT_BARRIER; /* */ /* Step 5. Wait until you receive message that the chile is at */ /* the barrier. */ if(mdebug>=1) printf("Master listening for child to send at barrier message.\n"); master_listen(master_listen_socket,sizeof(struct master_neutral_command)); mnc = (struct master_neutral_command *)&master_rcv_buf[0]; /* * Convert from string back to arch specific */ sscanf(mnc->m_client_number,"%d",&mc.m_client_number); #ifdef NO_PRINT_LLD sscanf(mnc->m_child_flag,"%ld",(long *)&mc.m_child_flag); #else sscanf(mnc->m_child_flag,"%lld",(long long *)&mc.m_child_flag); #endif child_index = mc.m_client_number; child_stat = (struct child_stats *)&shmaddr[child_index]; child_stat->flag = (long long)(mc.m_child_flag); if(mdebug>=1) printf("Master sees child %d at barrier message.\n",child_index); return(x); /* Tell code above that it is the parent returning */ } /****************************************************************************************/ /* This is the code that the client will use when it */ /* gets started via remote shell. It is activated by the -+c controller_name option. */ /* */ /* The steps to this process are: */ /* 1. Start client receive channel */ /* 2. Start client send channel */ /* 3. Send message to controller saying I'm joining. */ /* 4. Go into a loop and get all instructions from */ /* 5. Get state information from the master */ /* 6. Change to the working directory */ /* 7. Run the test */ /* 8. Release the listen and send sockets to the master */ /* */ /****************************************************************************************/ #ifdef HAVE_ANSIC_C void become_client(void) #else void become_client() #endif { int x,testnum; struct master_command mc; struct client_command cc; struct client_neutral_command *cnc; char client_name[100]; char *workdir; bzero(&mc,sizeof(struct master_command)); x=fork(); /* Become a daemon so that remote shell will return. */ if(x != 0) exit(0); /* * I am the child */ (void)gethostname(client_name,100); fflush(stdout); fflush(stderr); if(cdebug) { newstdin=freopen("/tmp/don_in","r+",stdin); newstdout=freopen("/tmp/don_out","a+",stdout); newstderr=freopen("/tmp/don_err","a+",stderr); } else { fclose(stdin); fclose(stdout); fclose(stderr); } if(cdebug>=1) { fprintf(newstdout,"My name = %s, Controller's name = %s\n",client_name, controlling_host_name); fflush(newstdout); } /* 1. Start client receive channel */ l_sock = start_child_listen(sizeof(struct client_neutral_command)); l_async_sock = start_child_listen_async(sizeof(struct client_neutral_command)); /* 2. Send message to controller saying I'm joining. */ strcpy(mc.m_host_name,controlling_host_name); strcpy(mc.m_client_name,client_name); mc.m_child_port = child_port; mc.m_child_async_port = child_async_port; mc.m_command = R_CHILD_JOIN; mc.m_version = proto_version; if(cdebug) { fprintf(newstdout,"Child %s sends JOIN to master %s Host Port %d\n", client_name,controlling_host_name,controlling_host_port); fflush(newstdout); } child_send(controlling_host_name,(struct master_command *)&mc, sizeof(struct master_command)); l_sock=child_attach(l_sock,0); l_async_sock=child_attach(l_async_sock,1); /* 4. Go into a loop and get all instructions from */ /* the controlling process. */ if(cdebug>=1) { fprintf(newstdout,"Child %s waiting for who am I\n",client_name); fflush(newstdout); } child_listen(l_sock,sizeof(struct client_neutral_command)); cnc = (struct client_neutral_command *)&child_rcv_buf; bzero(&cc, sizeof(struct client_command)); /* Convert from string format to arch format */ sscanf(cnc->c_command,"%d",&cc.c_command); sscanf(cnc->c_client_name,"%s",cc.c_client_name); sscanf(cnc->c_client_number,"%d",&cc.c_client_number); sscanf(cnc->c_host_name,"%s",cc.c_host_name); sscanf(cnc->c_pit_hostname,"%s",cc.c_pit_hostname); if(cc.c_command == R_TERMINATE || cc.c_command==R_DEATH) { if(cdebug) { fprintf(newstdout,"Child %d received terminate on sync channel !!\n",(int)chid); fflush(newstdout); } exit(1); } if(cdebug) { fprintf(newstdout,"Child sees: \n Client name %s \n Client_num # %d \n Host_name %s\n" ,cc.c_client_name,cc.c_client_number,cc.c_host_name); fflush(newstdout); } /* * Now import all of the values of the flags that the child on this * machine needs to be able to run the test requested. */ /* 5. Get state information from the master */ #ifdef NO_PRINT_LLD sscanf(cnc->c_numrecs64,"%ld",(long *)(&cc.c_numrecs64)); sscanf(cnc->c_reclen,"%ld",(long *)(&cc.c_reclen)); sscanf(cnc->c_fetchon,"%ld",(long *)(&cc.c_fetchon)); sscanf(cnc->c_purge,"%ld",(long *)(&cc.c_purge)); sscanf(cnc->c_delay,"%ld",(long *)(&cc.c_delay)); sscanf(cnc->c_stride,"%ld",(long *)(&cc.c_stride)); sscanf(cnc->c_rest_val,"%ld",(long *)(&cc.c_rest_val)); sscanf(cnc->c_delay_start,"%ld",(long *)(&cc.c_delay_start)); sscanf(cnc->c_depth,"%ld",(long *)(&cc.c_depth)); #else sscanf(cnc->c_numrecs64,"%lld",(long long *)(&cc.c_numrecs64)); sscanf(cnc->c_reclen,"%lld",(long long *)(&cc.c_reclen)); sscanf(cnc->c_fetchon,"%lld",(long long *)(&cc.c_fetchon)); sscanf(cnc->c_purge,"%lld",(long long *)(&cc.c_purge)); sscanf(cnc->c_delay,"%lld",(long long *)(&cc.c_delay)); sscanf(cnc->c_stride,"%lld",(long long *)(&cc.c_stride)); sscanf(cnc->c_rest_val,"%lld",(long long *)(&cc.c_rest_val)); sscanf(cnc->c_delay_start,"%lld",(long long *)(&cc.c_delay_start)); sscanf(cnc->c_depth,"%lld",(long long *)(&cc.c_depth)); #endif sscanf(cnc->c_pit_hostname,"%s",cc.c_pit_hostname); sscanf(cnc->c_pit_service,"%s",cc.c_pit_service); sscanf(cnc->c_testnum,"%d",&cc.c_testnum); sscanf(cnc->c_client_number,"%d",&cc.c_client_number); sscanf(cnc->c_working_dir,"%s",cc.c_working_dir); sscanf(cnc->c_file_name,"%s",cc.c_file_name); sscanf(cnc->c_write_traj_filename,"%s",cc.c_write_traj_filename); sscanf(cnc->c_read_traj_filename,"%s",cc.c_read_traj_filename); sscanf(cnc->c_noretest,"%d",&cc.c_noretest); sscanf(cnc->c_notruncate,"%d",&cc.c_notruncate); sscanf(cnc->c_read_sync,"%d",&cc.c_read_sync); sscanf(cnc->c_jflag,"%d",&cc.c_jflag); sscanf(cnc->c_direct_flag,"%d",&cc.c_direct_flag); sscanf(cnc->c_cpuutilflag,"%d",&cc.c_cpuutilflag); sscanf(cnc->c_seq_mix,"%d",&cc.c_seq_mix); sscanf(cnc->c_del_flag,"%d",&cc.c_del_flag); sscanf(cnc->c_async_flag,"%d",&cc.c_async_flag); sscanf(cnc->c_k_flag,"%d",&cc.c_k_flag); sscanf(cnc->c_h_flag,"%d",&cc.c_h_flag); sscanf(cnc->c_mflag,"%d",&cc.c_mflag); sscanf(cnc->c_pflag,"%d",&cc.c_pflag); sscanf(cnc->c_stride_flag,"%d",&cc.c_stride_flag); sscanf(cnc->c_verify,"%d",&cc.c_verify); sscanf(cnc->c_sverify,"%d",&cc.c_sverify); sscanf(cnc->c_odsync,"%d",&cc.c_odsync); sscanf(cnc->c_diag_v,"%d",&cc.c_diag_v); sscanf(cnc->c_zero_pct,"%d",&cc.c_zero_pct); sscanf(cnc->c_N_special,"%d",&cc.c_N_special); sscanf(cnc->c_dedup_granule_size,"%d",&cc.c_dedup_granule_size); sscanf(cnc->c_dedup_flag,"%d",&cc.c_dedup_flag); sscanf(cnc->c_dedup_iflag,"%d",&cc.c_dedup_iflag); sscanf(cnc->c_dedup_bflag,"%d",&cc.c_dedup_bflag); sscanf(cnc->c_dedup,"%d",&cc.c_dedup); sscanf(cnc->c_dedup_interior,"%d",&cc.c_dedup_interior); sscanf(cnc->c_dedup_compress,"%d",&cc.c_dedup_compress); sscanf(cnc->c_dedup_mseed,"%d",&cc.c_dedup_mseed); sscanf(cnc->c_chid_skew,"%d",&cc.c_chid_skew); sscanf(cnc->c_hist_summary,"%d",&cc.c_hist_summary); sscanf(cnc->c_op_rate,"%d",&cc.c_op_rate); sscanf(cnc->c_op_rate_flag,"%d",&cc.c_op_rate_flag); sscanf(cnc->c_file_lock,"%d",&cc.c_file_lock); sscanf(cnc->c_rec_lock,"%d",&cc.c_rec_lock); sscanf(cnc->c_Kplus_readers,"%d",&cc.c_Kplus_readers); sscanf(cnc->c_multiplier,"%d",&cc.c_multiplier); sscanf(cnc->c_share_file,"%d",&cc.c_share_file); sscanf(cnc->c_pattern,"%d",&cc.c_pattern); sscanf(cnc->c_version,"%d",&cc.c_version); sscanf(cnc->c_base_time,"%d",&cc.c_base_time); sscanf(cnc->c_num_child,"%d",&cc.c_num_child); sscanf(cnc->c_pct_read,"%d",&cc.c_pct_read); sscanf(cnc->c_advise_op,"%d",&cc.c_advise_op); sscanf(cnc->c_advise_flag,"%d",&cc.c_advise_flag); sscanf(cnc->c_restf,"%d",&cc.c_restf); sscanf(cnc->c_mygen,"%d",&cc.c_mygen); sscanf(cnc->c_oflag,"%d",&cc.c_oflag); sscanf(cnc->c_mfflag,"%d",&cc.c_mfflag); sscanf(cnc->c_unbuffered,"%d",&cc.c_unbuffered); sscanf(cnc->c_Q_flag,"%d",&cc.c_Q_flag); sscanf(cnc->c_inc_think,"%d",&cc.c_inc_think); sscanf(cnc->c_L_flag,"%d",&cc.c_L_flag); sscanf(cnc->c_xflag,"%d",&cc.c_xflag); sscanf(cnc->c_include_flush,"%d",&cc.c_include_flush); sscanf(cnc->c_OPS_flag,"%d",&cc.c_OPS_flag); sscanf(cnc->c_mmapflag,"%d",&cc.c_mmapflag); sscanf(cnc->c_mmapasflag,"%d",&cc.c_mmapasflag); sscanf(cnc->c_mmapnsflag,"%d",&cc.c_mmapnsflag); sscanf(cnc->c_mmapssflag,"%d",&cc.c_mmapssflag); sscanf(cnc->c_no_copy_flag,"%d",&cc.c_no_copy_flag); sscanf(cnc->c_w_traj_flag,"%d",&cc.c_w_traj_flag); sscanf(cnc->c_r_traj_flag,"%d",&cc.c_r_traj_flag); sscanf(cnc->c_no_unlink,"%d",&cc.c_no_unlink); sscanf(cnc->c_no_write,"%d",&cc.c_no_write); sscanf(cnc->c_include_close,"%d",&cc.c_include_close); sscanf(cnc->c_disrupt_flag,"%d",&cc.c_disrupt_flag); sscanf(cnc->c_compute_flag,"%d",&cc.c_compute_flag); sscanf(cnc->c_MS_flag,"%d",&cc.c_MS_flag); sscanf(cnc->c_mmap_mix,"%d",&cc.c_mmap_mix); sscanf(cnc->c_Kplus_flag,"%d",&cc.c_Kplus_flag); sscanf(cnc->c_compute_time,"%f",&cc.c_compute_time); strcpy(write_traj_filename,cc.c_write_traj_filename); strcpy(read_traj_filename,cc.c_read_traj_filename); numrecs64 = cc.c_numrecs64; strcpy(pit_hostname,cc.c_pit_hostname); strcpy(pit_service,cc.c_pit_service); reclen = cc.c_reclen; testnum = cc.c_testnum; chid = cc.c_client_number; workdir=cc.c_working_dir; oflag = cc.c_oflag; /* Child's absolute filename to use is provided */ mfflag = cc.c_mfflag; if(mfflag) strcpy(filearray[chid],cc.c_file_name); if(cdebug) { fprintf(newstdout,"File name given %s\n",cc.c_file_name); fflush(newstdout); } unbuffered = cc.c_unbuffered; noretest = cc.c_noretest; notruncate = cc.c_notruncate; read_sync = cc.c_read_sync; jflag = cc.c_jflag; direct_flag = cc.c_direct_flag; cpuutilflag = cc.c_cpuutilflag; seq_mix = cc.c_seq_mix; del_flag = cc.c_del_flag; async_flag = cc.c_async_flag; k_flag = cc.c_k_flag; h_flag = cc.c_h_flag; mflag = cc.c_mflag; pflag = cc.c_pflag; stride_flag = cc.c_stride_flag; fetchon = cc.c_fetchon; verify = cc.c_verify; diag_v = cc.c_diag_v; zero_pct = cc.c_zero_pct; N_special = cc.c_N_special; dedup_granule_size = cc.c_dedup_granule_size; dedup = cc.c_dedup; dedup_flag = cc.c_dedup_flag; dedup_iflag = cc.c_dedup_iflag; dedup_bflag = cc.c_dedup_bflag; dedup_interior = cc.c_dedup_interior; dedup_compress = cc.c_dedup_compress; dedup_mseed = cc.c_dedup_mseed; chid_skew = cc.c_chid_skew; hist_summary = cc.c_hist_summary; op_rate = cc.c_op_rate; op_rate_flag = cc.c_op_rate_flag; if(diag_v) sverify = 0; else sverify = cc.c_sverify; file_lock = cc.c_file_lock; rlocking = cc.c_rec_lock; Kplus_readers = cc.c_Kplus_readers; multiplier = cc.c_multiplier; share_file = cc.c_share_file; pattern = cc.c_pattern; /* proto_version = cc.c_version; Don't copy it back. */ base_time=cc.c_base_time; num_child=(long long)cc.c_num_child; pct_read=cc.c_pct_read; advise_op=cc.c_advise_op; advise_flag=cc.c_advise_flag; restf=cc.c_restf; mygen=cc.c_mygen; Q_flag = cc.c_Q_flag; inc_think = cc.c_inc_think; L_flag = cc.c_L_flag; xflag = cc.c_xflag; w_traj_flag = cc.c_w_traj_flag; r_traj_flag = cc.c_r_traj_flag; include_flush = cc.c_include_flush; OPS_flag = cc.c_OPS_flag; purge = cc.c_purge; mmapflag = cc.c_mmapflag; mmapasflag = cc.c_mmapasflag; mmapnsflag = cc.c_mmapnsflag; mmapssflag = cc.c_mmapssflag; no_copy_flag = cc.c_no_copy_flag; no_unlink = cc.c_no_unlink; no_write = cc.c_no_write; include_close = cc.c_include_close; disrupt_flag = cc.c_disrupt_flag; compute_flag = cc.c_compute_flag; MS_flag = cc.c_MS_flag; mmap_mix = cc.c_mmap_mix; Kplus_flag = cc.c_Kplus_flag; delay = cc.c_delay; stride = cc.c_stride; rest_val = cc.c_rest_val; depth = cc.c_depth; delay_start = cc.c_delay_start; compute_time = cc.c_compute_time; if(N_special) touch_dedup(buffer1, MAXBUFFERSIZE); if(cdebug) { fprintf(newstdout,"Child %d change directory to %s\n",(int)chid,workdir); fflush(newstdout); } if(purge) alloc_pbuf(); /* 6. Change to the working directory */ if(chdir(workdir)<0) client_error=errno; start_child_listen_loop(); /* The async channel listener */ /* Need to start this after getting into the correct directory */ if(w_traj_flag) w_traj_size(); if(r_traj_flag) r_traj_size(); get_resolution(); /* Get my clock resolution */ if(hist_summary) { printf("Child got HISTORY flag\n"); } /* 7. Run the test */ switch(testnum) { case THREAD_WRITE_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_write_test\n",(int)chid); fflush(newstdout); } thread_write_test(0); break; #ifdef HAVE_PREAD case THREAD_PWRITE_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_pwrite_test\n",(int)chid); fflush(newstdout); } thread_pwrite_test(0); break; #endif case THREAD_REWRITE_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_rewrite_test\n",(int)chid); fflush(newstdout); } thread_rwrite_test(0); break; case THREAD_READ_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_read_test\n",(int)chid); fflush(newstdout); } thread_read_test(0); break; #ifdef HAVE_PREAD case THREAD_PREAD_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_read_test\n",(int)chid); fflush(newstdout); } thread_pread_test(0); break; #endif case THREAD_REREAD_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_reread_test\n",(int)chid); fflush(newstdout); } thread_rread_test(0); break; case THREAD_STRIDE_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_stride_read_test\n",(int)chid); fflush(newstdout); } thread_stride_read_test(0); break; case THREAD_RANDOM_READ_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running random read test\n",(int)chid); fflush(newstdout); } thread_ranread_test(0); break; case THREAD_RANDOM_WRITE_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running random write test\n",(int)chid); fflush(newstdout); } thread_ranwrite_test(0); break; case THREAD_REVERSE_READ_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running reverse read test\n",(int)chid); fflush(newstdout); } thread_reverse_read_test(0); break; case THREAD_RANDOM_MIX_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running mixed workload test\n",(int)chid); fflush(newstdout); } thread_mix_test(0); break; case THREAD_FWRITE_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_fwrite_test\n",(int)chid); fflush(newstdout); } thread_fwrite_test(0); break; case THREAD_FREAD_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running thread_fread_test\n",(int)chid); fflush(newstdout); } thread_fread_test(0); break; case THREAD_CLEANUP_TEST : if(cdebug>=1) { fprintf(newstdout,"Child %d running cleanup\n",(int)chid); fflush(newstdout); } thread_cleanup_test(0); break; }; if(cdebug>=1) { fprintf(newstdout,"Child %d finished running test.\n",(int)chid); fflush(newstdout); } /* 8. Release the listen and send sockets to the master */ stop_child_listen(l_sock); exit(0); } /* * Clients tell the master their statistics, set the stopped flag, and set shared memory * child_flag to tell the master they are finished. Also each client report all statistics. */ #ifdef HAVE_ANSIC_C void tell_master_stats(int testnum , long long chid, double throughput, double actual, float cpu_time, double wall_time, char stop_flag, long long child_flag) #else void tell_master_stats(testnum , chid, throughput, actual, cpu_time, wall_time, stop_flag, child_flag) int testnum; long long chid; double throughput, actual, wall_time; char stop_flag; float cpu_time; long long child_flag; #endif { struct master_command mc; bzero(&mc,sizeof(struct master_command)); mc.m_client_number = (int) chid; mc.m_client_error = (int) client_error; mc.m_throughput= throughput; mc.m_testnum = testnum; mc.m_actual = actual; mc.m_cputime = cpu_time; mc.m_walltime = wall_time; mc.m_stop_flag = stop_flag; mc.m_child_flag = child_flag; mc.m_command = R_STAT_DATA; mc.m_mygen = mygen; mc.m_version = proto_version; if(cdebug>=1) { fprintf(newstdout,"Child %d: Tell master stats and terminate\n",(int)chid); fflush(newstdout); } child_send(controlling_host_name,(struct master_command *)&mc, sizeof(struct master_command)); } /* * Stop the master listener loop service. * Currently this is not used. The master_join_count * variable is used to terminate the loop service. */ #ifdef HAVE_ANSIC_C void stop_master_listen_loop(void) #else void stop_master_listen_loop() #endif { if(mdebug>=1) printf("Stopping Master listen loop"); kill(master_listen_pid,SIGKILL); } /* * Clients tell the master that I am at the barrier and ready * for the message to start work. */ #ifdef HAVE_ANSIC_C void tell_master_ready(long long chid) #else void tell_master_ready(chid) long long chid; #endif { struct master_command mc; bzero(&mc,sizeof(struct master_command)); if(cdebug>=1) { fprintf(newstdout,"Child %d: Tell master to go\n",(int)chid); fflush(newstdout); } mc.m_command = R_FLAG_DATA; mc.m_mygen = mygen; mc.m_version = proto_version; mc.m_child_flag = CHILD_STATE_READY; mc.m_client_number = (int)chid; mc.m_client_error = client_error; child_send(controlling_host_name,(struct master_command *)&mc, sizeof(struct master_command)); } /* * Clients wait at a barrier for the master to tell them * to begin work. This is the function where they wait. */ #ifdef HAVE_ANSIC_C void wait_for_master_go(long long chid) #else void wait_for_master_go(chid) long long chid; #endif { struct client_neutral_command *cnc; struct client_command cc; bzero(&cc,sizeof(struct client_command)); child_listen(l_sock,sizeof(struct client_neutral_command)); cnc = (struct client_neutral_command *)child_rcv_buf; sscanf(cnc->c_command,"%d",&cc.c_command); if(cc.c_command == R_TERMINATE || cc.c_command==R_DEATH) { if(cdebug) { fprintf(newstdout,"Child %d received terminate on sync channel at barrier !!\n",(int)chid); fflush(newstdout); } exit(1); } if(cdebug>=1) { fprintf(newstdout,"Child %d return from wait_for_master_go\n",(int)chid); fflush(newstdout); } } /* * Create a master listener for receiving data from the * many children. As the children finish they will send * their statistics and terminate. When the master_join_count * goes to zero then it is time to stop this service. * When this service exits then the parent will know * that all of the children are done. */ #ifdef HAVE_ANSIC_C void start_master_listen_loop(int num) #else void start_master_listen_loop(num) int num; #endif { int i; struct child_stats *child_stat; struct master_neutral_command *mnc; struct master_command mc; int temp; struct timespec req,rem; req.tv_sec = 0; req.tv_nsec = 10000000; rem.tv_sec = 0; rem.tv_nsec = 10000000; master_join_count=num; master_listen_pid=fork(); if(master_listen_pid!=0) return; if(mdebug>=1) printf("Starting Master listen loop m %d c %d count %d\n",master_iozone, client_iozone,num); while(master_join_count) { master_listen(master_listen_socket,sizeof(struct master_neutral_command)); mnc=(struct master_neutral_command *)&master_rcv_buf[0]; /* * Convert from string format to arch format */ sscanf(mnc->m_command,"%d",&mc.m_command); sscanf(mnc->m_client_number,"%d",&mc.m_client_number); sscanf(mnc->m_client_error,"%d",&mc.m_client_error); sscanf(mnc->m_mygen,"%d",&mc.m_mygen); sscanf(mnc->m_version,"%d",&mc.m_version); if(mc.m_version != proto_version) { printf("Client # %d is not running the same version of Iozone !\n", mc.m_client_number); } if(mc.m_client_error != 0) { printf("\nClient # %d reporting an error %s !\n", mc.m_client_number,strerror(mc.m_client_error)); } #ifdef NO_PRINT_LLD sscanf(mnc->m_child_flag,"%ld",&mc.m_child_flag); #else sscanf(mnc->m_child_flag,"%lld",&mc.m_child_flag); #endif sscanf(mnc->m_actual,"%f",&mc.m_actual); sscanf(mnc->m_throughput,"%f",&mc.m_throughput); sscanf(mnc->m_cputime,"%f",&mc.m_cputime); sscanf(mnc->m_walltime,"%f",&mc.m_walltime); sscanf(mnc->m_stop_flag,"%d",&temp); mc.m_stop_flag = temp; switch(mc.m_command) { case R_STAT_DATA: if(mc.m_mygen != mygen) { /* * >>> You are NOT one of my children !!! <<< * Probably children left behind from another run !!! * Ignore their messages, and go on without them. */ printf("*** Unknown Iozone children responding !!! ***\n"); continue; } i = mc.m_client_number; if(mdebug) printf("loop: R_STAT_DATA for client %d\n",i); child_stat = (struct child_stats *)&shmaddr[i]; child_stat->flag = mc.m_child_flag; child_stat->actual = mc.m_actual; child_stat->throughput = mc.m_throughput; child_stat->cputime = mc.m_cputime; child_stat->walltime = mc.m_walltime; *stop_flag = mc.m_stop_flag; master_join_count--; break; case R_FLAG_DATA: if(mc.m_mygen != mygen) { /* You are NOT one of my children !!! */ printf("*** Unknown Iozone children responding !!! ***\n"); continue; } if(mdebug) printf("loop: R_FLAG_DATA: Client %d flag %d \n", (int)mc.m_client_number, (int)mc.m_child_flag); i = mc.m_client_number; child_stat = (struct child_stats *)&shmaddr[i]; child_stat->flag = (long long)(mc.m_child_flag); break; case R_STOP_FLAG: if(mc.m_mygen != mygen) { /* You are NOT one of my children !!! */ printf("*** Unknown Iozone children responding !!! ***\n"); continue; } if(mdebug) printf("Master loop: R_STOP_FLAG: Client %d STOP_FLAG \n", (int)mc.m_client_number); *stop_flag=1; distribute_stop(); break; } } /* Let the clients report results before exiting. Also, exiting too quickly can close the async socket to the child, and cause it to become ill. On Solaris, it gets stuck in a 0=read() loop. */ #if defined(Windows) sleep(1); #else nanosleep(&req,&rem); #endif exit(0); } /* * Create a client listener for receiving async data from the * the master. */ #ifdef HAVE_ANSIC_C void start_child_listen_loop(void) #else void start_child_listen_loop() #endif { int i; struct child_stats *child_stat; struct client_command cc; struct client_neutral_command *cnc; client_listen_pid=fork(); if(client_listen_pid!=0) return; if(cdebug>=1) { fprintf(newstdout,"Child %d starting client listen loop\n",(int)chid); fflush(newstdout); } while(1) { bzero(&cc,sizeof(struct client_command)); child_listen_async(l_async_sock,sizeof(struct client_neutral_command)); cnc=(struct client_neutral_command *)&child_async_rcv_buf; /* * Convert from string format to arch format */ sscanf(cnc->c_command,"%d",&cc.c_command); sscanf(cnc->c_client_number,"%d",&cc.c_client_number); sscanf(cnc->c_stop_flag,"%d",&cc.c_stop_flag); switch(cc.c_command) { case R_STOP_FLAG: i = cc.c_client_number; if(cdebug) { fprintf(newstdout,"child loop: R_STOP_FLAG for client %d\n",i); fflush(newstdout); } child_stat = (struct child_stats *)&shmaddr[i]; *stop_flag = cc.c_stop_flag; /* In shared memory with other copy */ sent_stop=1; break; case R_TERMINATE: if(cdebug) { fprintf(newstdout,"Child loop: R_TERMINATE: Client %d \n", (int)cc.c_client_number); fflush(newstdout); } sleep(2); /* Aync listener goes away */ stop_child_listen(l_async_sock); exit(0); case R_DEATH: if(cdebug) { fprintf(newstdout,"Child loop: R_DEATH: Client %d \n", (int)cc.c_client_number); fflush(newstdout); } i = cc.c_client_number; child_remove_files(i); sleep(2); /* Aync listener goes away */ stop_child_listen(l_async_sock); exit(0); } } } /* * The controlling process "master" tells the children to begin. */ #ifdef HAVE_ANSIC_C void tell_children_begin(long long childnum) #else void tell_children_begin(childnum) long long childnum; #endif { struct client_command cc; int x; bzero(&cc,sizeof(struct client_command)); x = (int) childnum; if(mdebug>=1) printf("Master: Tell child %d to begin\n",x); cc.c_zero_pct = zero_pct; cc.c_N_special = N_special; cc.c_dedup_granule_size = dedup_granule_size; cc.c_command = R_FLAG_DATA; cc.c_child_flag = CHILD_STATE_BEGIN; cc.c_client_number = (int)childnum; master_send(master_send_sockets[x],child_idents[x].child_name, &cc,sizeof(struct client_command)); } /* * The master waits here for all of the the children to terminate. * When the children are done the the master_join_count will be at zero * and the master_listen_loop will exit. This function waits for this to happen. */ #ifdef HAVE_ANSIC_C void wait_dist_join(void) #else void wait_dist_join() #endif { wait(0); if(mdebug) printf("Master: All children have finished. Sending terminate\n"); terminate_child_async(); /* All children are done, so terminate their async channel */ current_client_number=0; /* start again */ } /* * This function reads a file that contains client information. * The information is: * client name (DNS usable name) * client working directory (where to run the test) * client directory that contains the Iozone executable. * * If the first character in a line is a # then it is a comment. * The maximum number of clients is MAXSTREAMS. */ #ifdef HAVE_ANSIC_C int get_client_info(void) #else int get_client_info() #endif { FILE *fd; char *ret1; int count; char buffer[800]; count=0; fd=fopen(client_filename,"r"); if(fd == (FILE *)NULL) { printf("Unable to open client file \"%s\"\n", client_filename); exit(176); } while(1) { if (count > MAXSTREAMS) { printf("Too many lines in client file - max of %d supported\n", MAXSTREAMS); exit(7); } ret1=fgets(buffer,800,fd); if(ret1== (char *)NULL) break; count+=parse_client_line(buffer,count); } fclose(fd); return(count); } /* * This function parses a line from the client file. It is * looking for: * Client name (DNS usable) * Client working directory (where to run the test ) * Client path to Iozone executable. * * Lines that start with # are comments. */ #ifdef HAVE_ANSIC_C int parse_client_line(char *buffer,int line_num) #else int parse_client_line(buffer, line_num) char *buffer; int line_num; #endif { int num; /* Format is clientname, workdir, execute_path */ /* If column #1 contains a # symbol then skip this line */ if(buffer[0]=='#') return(0); num=sscanf(buffer,"%s %s %s %s\n", child_idents[line_num].child_name, child_idents[line_num].workdir, child_idents[line_num].execute_path, child_idents[line_num].file_name); if((num < 0) || ((num > 0) && (num !=3) && (num !=4))) { printf("Bad Client Identity at entry %d\n",line_num); printf("Client: -> %s Workdir: -> %s Execute_path: -> %s \n", child_idents[line_num].child_name, child_idents[line_num].workdir, child_idents[line_num].execute_path); exit(203); } if(num == 4) mfflag++; return(1); } /* * This is a mechanism that the child uses to remove all * of its temporary files. Only used at terminate time. */ #ifdef HAVE_ANSIC_C void child_remove_files(int i) #else void child_remove_files(i) int i; #endif { char *dummyfile[MAXSTREAMS]; /* name of dummy file */ dummyfile[i]=(char *)malloc((size_t)MAXNAMESIZE); if(mfflag) { sprintf(dummyfile[i],"%s",filearray[i]); } else { sprintf(dummyfile[i],"%s.DUMMY.%d",filearray[i],i); } if(cdebug) { fprintf(newstdout,"Child %d remove: %s \n",(int)chid, dummyfile[i]); fflush(newstdout); } if(check_filename(dummyfile[i])) unlink(dummyfile[i]); } /* * The master tells the child async listener that it is time * to terminate its services. */ #ifdef HAVE_ANSIC_C void terminate_child_async(void) #else void terminate_child_async() #endif { int i; struct client_command cc; bzero(&cc,sizeof(struct client_command)); cc.c_command = R_TERMINATE; for(i=0;i>>>> Client Network Speed check <<<<< *\n"); printf("***************************************************\n\n"); printf("Master: %s\n",sp_master_host); printf("Transfer size %d bytes \n",sp_msize); printf("Count %d\n",sp_count); printf("Total size %d kbytes \n\n", (sp_msize*sp_count)/1024); sp_once=1; } sp_dest=sp_remote_host; sleep(1); sp_do_master_t(); free(sp_buf); } } /* * Get results back from the client. */ #ifdef HAVE_ANSIC_C void sp_get_result(int port,int flag) #else void sp_get_result(port,flag) int port,flag; #endif { int tcfd; float throughput; int count; char mybuf[1024]; int sp_offset,xx; tcfd=sp_start_master_listen(port, 1024); sp_offset=0; while(sp_offset < 1024) { xx=read(tcfd,&mybuf[sp_offset],1024); sp_offset+=xx; } sscanf(mybuf,"%d %f",&count,&throughput); if(!flag) printf("%-20s received %10d kBytes @ %10.2f kBytes/sec \n", sp_remote_host,count,throughput); else printf("%-20s sent %10d kBytes @ %10.2f kBytes/sec \n", sp_remote_host,count,throughput); close(tcfd); } /* * Send results to the master. */ #ifdef HAVE_ANSIC_C void sp_send_result(int port, int count, float throughput) #else void sp_send_result(port, count, throughput) int port,count; float throughput; #endif { int msfd; char mybuf[1024]; sprintf(mybuf,"%d %f",count, throughput); msfd=sp_start_child_send(sp_dest, port, &sp_my_cs_addr); junk=write(msfd,mybuf,1024); if(cdebug) { fprintf(newstdout,"Sending result\n"); fflush(newstdout); } close(msfd); } /* * Start the channel for the master to send a message to * a child on a port that the child * has created for the parent to use to communicate. */ #ifdef HAVE_ANSIC_C int sp_start_master_send(char *sp_child_host_name, int sp_child_listen_port, struct in_addr *sp_my_ms_addr) #else int sp_start_master_send(sp_child_host_name, sp_child_listen_port, sp_my_ms_addr) char *sp_child_host_name; int sp_child_listen_port; struct in_addr *sp_my_ms_addr; #endif { int rc,master_socket_val; struct sockaddr_in addr,raddr; struct hostent *he; int port,tmp_port; int ecount=0; struct in_addr *ip; struct timespec req,rem; req.tv_sec = 0; req.tv_nsec = 10000000; rem.tv_sec = 0; rem.tv_nsec = 10000000; he = gethostbyname(sp_child_host_name); if (he == NULL) { printf("Master: Bad hostname >%s<\n",sp_child_host_name); fflush(stdout); exit(22); } if(mdebug ==1) { printf("Master: start master send: %s\n", he->h_name); fflush(stdout); } ip = (struct in_addr *)he->h_addr_list[0]; #ifndef UWIN if(mdebug ==1) { printf("Master: child name: %s\n", (char *)inet_ntoa(*ip)); printf("Master: child Port: %d\n", sp_child_listen_port); fflush(stdout); } #endif port=sp_child_listen_port; sp_my_ms_addr->s_addr = ip->s_addr; /*port=CHILD_LIST_PORT;*/ raddr.sin_family = AF_INET; raddr.sin_port = htons(port); raddr.sin_addr.s_addr = ip->s_addr; master_socket_val = socket(AF_INET, SOCK_STREAM, 0); if (master_socket_val < 0) { perror("Master: socket failed:"); exit(23); } bzero(&addr, sizeof(struct sockaddr_in)); tmp_port=sp_master_esend_port; addr.sin_port = htons(tmp_port); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(master_socket_val, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; addr.sin_port=htons(tmp_port); continue; } } if(mdebug ==1) { printf("Master: Bound port\n"); fflush(stdout); } if (rc < 0) { perror("Master: bind failed for sync channel to child.\n"); exit(24); } #if defined(Windows) sleep(1); #else nanosleep(&req,&rem); #endif again: rc = connect(master_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++ < 300) { #if defined(Windows) sleep(1); #else nanosleep(&req,&rem); #endif /*sleep(1);*/ goto again; } perror("Master: connect failed\n"); printf("Error %d\n",errno); exit(25); } if(mdebug ==1) { printf("Master Connected\n"); fflush(stdout); } return (master_socket_val); } /* * Start the childs listening service for messages from the master. */ #ifdef HAVE_ANSIC_C int sp_start_child_listen(int listen_port, int size_of_message) #else int sp_start_child_listen(listen_port, size_of_message) int listen_port; int size_of_message; #endif { int tsize; int s,ns; unsigned int me; int rc; int xx; int tmp_port; struct sockaddr_in *addr; int sockerr; int recv_buf_size=65536; int optval=1; xx = 0; me=sizeof(struct sockaddr_in); tsize=size_of_message; /* Number of messages to receive */ s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("socket failed:"); exit(19); } sockerr = setsockopt (s, SOL_SOCKET, SO_RCVBUF, (char *) &recv_buf_size, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 7\n"); } sockerr = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, sizeof(int)); if ( sockerr == -1 ) { perror("Error in setsockopt 8\n"); } bzero(&sp_child_sync_sock, sizeof(struct sockaddr_in)); tmp_port=sp_child_listen_port; sp_child_sync_sock.sin_port = htons(tmp_port); sp_child_sync_sock.sin_family = AF_INET; sp_child_sync_sock.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(s, (struct sockaddr *)&sp_child_sync_sock, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; sp_child_sync_sock.sin_port=htons(tmp_port); continue; } } sp_child_listen_port = ntohs(sp_child_sync_sock.sin_port); if(cdebug ==1) { fprintf(newstdout,"Child: Listen: Bound at port %d\n", tmp_port); fflush(newstdout); } if(rc < 0) { if(cdebug ==1) { fprintf(newstdout,"bind failed. Errno %d\n", errno); fflush(newstdout); } exit(20); } addr=&sp_child_async_sock; listen(s,10); if(cdebug) { fprintf(newstdout,"Child enters accept\n"); fflush(newstdout); } #if defined(ANDROID) ns=accept((int)s,(struct sockaddr *)addr,(socklen_t *)&me); #else ns=accept(s,(void *)addr,&me); #endif if(cdebug) { fprintf(newstdout,"Child attached for receive. Sock %d %d\n", ns,errno); fflush(newstdout); } close(s); return(ns); } /* * The client runs this code */ #ifdef HAVE_ANSIC_C void sp_do_child_t(void) #else void sp_do_child_t() #endif { int i,y; int offset; int sp_tcount=0; /* child */ /* * Child reads from master */ sp_crfd=sp_start_child_listen(sp_child_listen_port, sp_msize); sp_start_time=time_so_far(); for(i=0;i%s<\n",sp_master_host_name); fflush(stdout); exit(22); } if(cdebug ==1) { fprintf(newstdout,"Child: start child send: %s\n", he->h_name); fprintf(newstdout,"To: %s at port %d\n",sp_master_host_name, sp_master_listen_port); fflush(newstdout); } ip = (struct in_addr *)he->h_addr_list[0]; port=sp_master_listen_port; sp_my_cs_addr->s_addr = ip->s_addr; raddr.sin_family = AF_INET; raddr.sin_port = htons(port); raddr.sin_addr.s_addr = ip->s_addr; sp_child_socket_val = socket(AF_INET, SOCK_STREAM, 0); if (sp_child_socket_val < 0) { perror("child: socket failed:"); exit(23); } bzero(&addr, sizeof(struct sockaddr_in)); tmp_port=sp_child_esend_port; addr.sin_port = htons(tmp_port); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; rc = -1; while (rc < 0) { rc = bind(sp_child_socket_val, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if(rc < 0) { tmp_port++; addr.sin_port=htons(tmp_port); continue; } } if(cdebug ==1) { fprintf(newstdout,"Child: Bound port %d\n",tmp_port); fflush(newstdout); } if (rc < 0) { perror("Child: bind failed for sync channel to child.\n"); exit(24); } #if defined(Windows) sleep(1); #else nanosleep(&req,&rem); #endif again: rc = connect(sp_child_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++<300) { #if defined(Windows) sleep(1); #else nanosleep(&req,&rem); #endif goto again; } fprintf(newstdout,"child: connect failed. Errno %d \n",errno); fflush(newstdout); exit(25); } if(cdebug ==1) { fprintf(newstdout,"child Connected\n"); fflush(newstdout); } return (sp_child_socket_val); } #ifdef HAVE_ANSIC_C void do_speed_check(int client_flag) #else void do_speed_check(client_flag) int client_flag; #endif { int i; if(client_flag) { speed_main(" "," ",reclen,kilobytes64,client_flag); } else { printf("Checking %d clients\n",clients_found); for(i=0;i xor ops * Seed composed from: blocknumber (do not include childnum as you want duplicates) * size ... size of buffers. (in bytes) * percent. Percent of buffer to modify. * percent_interior. Percent of buffer that is dedupable within * and across files * percent_compress. Percent of buffer that is dedupable within * but not across files * * Returns 0 (zero) for success, and -1 (minus one) for failure. */ int special_gen_new_buf(char *ibuf, char *obuf, long seed, int size, int percent, int percent_interior, int percent_compress, int all) { register int *ip, *op; /* Register for speed */ register int iseed; /* Register for speed */ register int isize; /* Register for speed */ register int cseed; /* seed for dedupable for within & ! across */ register int x,w; /* Register for speed */ register int value; /* Register for speed */ register int interior_size; /* size of interior dedup region */ register int compress_size; /* size of compression dedup region */ int base = seed * reclen; if(ibuf == NULL) /* no input buf */ return(-1); if(obuf == NULL) /* no output buf */ return(-1); if((percent > 100) || (percent < 0)) /* percent check */ return(-1); if(size == 0) /* size check */ return(-1); srand(seed+1+(((int)numrecs64)*dedup_mseed)); /* set random seed */ iseed =rand(); isize = (size * percent)/100; /* percent that is dedupable */ interior_size = ((isize * percent_interior)/100);/* /sizeof(long) */ compress_size =((interior_size * percent_compress)/100); ip = (int *)ibuf; /* pointer to input buf */ op = (int *)obuf; /* pointer to output buf */ if(all == 0) /* Special case for verify only */ isize = sizeof(int); /* dedup region boundary */ /* [0,interior_size-compress_size) : dedupable within and across */ /* [interior_size-compress_size, interior_size) : dedupable within only */ /* [interior_size, isize] : dedupable across only */ /* [isize, size] : non-dedupable */ /* check whether each dedup region is starting a dedup unit */ /* printf("within&across@0 within@%08x across@%08x nondedup@%x\n", */ /* interior_size-compress_size,interior_size, isize); */ /* if ( (interior_size-compress_size) %dedup_granule != 0) */ /* printf("warning: dedup region(within only) is starting in the */ /* middle of a dedup unit\n"); */ /* if ( interior_size %dedup_granule_size != 0) */ /* printf("warning: dedup region(across only) is starting in the */ /* middle of a dedup unit\n"); */ /* if ( isize %dedup_granule_size != 0) */ /* printf("warning: nondedup region is starting in the middle of */ /* a unit\n"); */ /* interior_size = dedup_within + dedup_across */ /* /for(w=0;w>12); ip++; *op++=0xdead; ip++; x+=sizeof(int); blkidx[chid]++; } else { op++; ip++; } } if(all == 0) /* Special case for verify only */ return(0); /* make the rest of the buffer non-dedupable */ if(100-percent > 0) { srand(1+seed+((chid+1)*(int)numrecs64)*dedup_mseed); value=rand(); for( ; x>12); ip++; blkidx[chid]++; x+= sizeof(int); } else { ip++; op++; } } } return(0); } long compressible_rand(void) { /* zero_pct:[0,100] */ int toss = ((((double)rand()/((double)MAX_RAND+(double)1))*100+1)); if (toss>zero_pct) { return (long)(((double)rand()/((double)MAX_RAND+(double)1))*MAX_RAND)+1; /* [1,MAX_RAND]. avoid zeros because */ /* zeros are used for compressibility control */ } else { return 0; } } /* * Used to touch all of the buffers so that the CPU data * cache is hot, and not part of the measurement. * This is for mixed mode of compression + dedup. */ void new_touch_dedup(char *i, int size) { register int x; register int *ip; ip = (int *)i; /* To make sure every fileset generates different dedup patterns */ srand(DEDUPSEED+dedup_mseed); for(x=0;x<(int)(size/sizeof(int));x++) { if ( zero_pct >= 0 ) { *ip=compressible_rand(); /* fill initial buffer */ } ip++; } } /* A C-program for MT19937-64 (2004/9/29 version). Coded by Takuji Nishimura and Makoto Matsumoto. This is a 64-bit version of Mersenne Twister pseudorandom number generator. Before using, initialize the state by using init_genrand64(seed) or init_by_array64(init_key, key_length). Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. References: T. Nishimura, ``Tables of 64-bit Mersenne Twisters'' ACM Transactions on Modeling and Computer Simulation 10. (2000) 348--357. M. Matsumoto and T. Nishimura, ``Mersenne Twister: a 623-dimensionally equidistributed uniform pseudorandom number generator'' ACM Transactions on Modeling and Computer Simulation 8. (Jan. 1998) 3--30. Any feedback is very welcome. http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces) */ #define NN 312 #define MM 156 #define MATRIX_A 0xB5026F5AA96619E9ULL #define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ #define LM 0x7FFFFFFFULL /* Least significant 31 bits */ /* The array for the state vector */ static unsigned long long mt[NN]; /* mti==NN+1 means mt[NN] is not initialized */ static int mti=NN+1; /* initializes mt[NN] with a seed */ void init_genrand64(unsigned long long seed) { mt[0] = seed; for (mti=1; mti> 62)) + mti); } /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ void init_by_array64(unsigned long long init_key[], unsigned long long key_length) { unsigned long long i, j, k; init_genrand64(19650218ULL); i=1; j=0; k = (NN>key_length ? NN : key_length); for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ULL)) + init_key[j] + j; /* non linear */ i++; j++; if (i>=NN) { mt[0] = mt[NN-1]; i=1; } if (j>=key_length) j=0; } for (k=NN-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ULL)) - i; /* non linear */ i++; if (i>=NN) { mt[0] = mt[NN-1]; i=1; } } mt[0] = 1ULL << 63; /* MSB is 1; assuring non-zero initial array */ } /* generates a random number on [0, 2^64-1]-interval */ unsigned long long genrand64_int64(void) { int i; unsigned long long x; static unsigned long long mag01[2]={0ULL, MATRIX_A}; if (mti >= NN) { /* generate NN words at one time */ /* if init_genrand64() has not been called, */ /* a default initial seed is used */ if (mti == NN+1) init_genrand64(5489ULL); for (i=0;i>1) ^ mag01[(int)(x&1ULL)]; } for (;i>1) ^ mag01[(int)(x&1ULL)]; } x = (mt[NN-1]&UM)|(mt[0]&LM); mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; mti = 0; } x = mt[mti++]; x ^= (x >> 29) & 0x5555555555555555ULL; x ^= (x << 17) & 0x71D67FFFEDA60000ULL; x ^= (x << 37) & 0xFFF7EEE000000000ULL; x ^= (x >> 43); return x; } /* generates a random number on [0, 2^63-1]-interval */ long long genrand64_int63(void) { return (long long)(genrand64_int64() >> 1); } /* generates a random number on [0,1]-real-interval */ double genrand64_real1(void) { return (genrand64_int64() >> 11) * (1.0/9007199254740991.0); } /* generates a random number on [0,1)-real-interval */ double genrand64_real2(void) { return (genrand64_int64() >> 11) * (1.0/9007199254740992.0); } /* generates a random number on (0,1)-real-interval */ double genrand64_real3(void) { return ((genrand64_int64() >> 12) + 0.5) * (1.0/4503599627370496.0); } #ifdef MT_TEST int main(void) { int i; unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}, length=4; init_by_array64(init, length); printf("1000 outputs of genrand64_int64()\n"); for (i=0; i<1000; i++) { printf("%20llu ", genrand64_int64()); if (i%5==4) printf("\n"); } printf("\n1000 outputs of genrand64_real2()\n"); for (i=0; i<1000; i++) { printf("%10.8f ", genrand64_real2()); if (i%5==4) printf("\n"); } return 0; } #endif /*----------------------------------------------------------------------*/ /* */ /* The PIT Programmable Interdimensional Timer */ /* */ /* This is used to measure time, when you know something odd is going */ /* to be happening with your wrist watch. For example, you have entered */ /* a temporal distortion field where time its-self is not moving */ /* as it does in your normal universe. ( thing either intense */ /* gravitational fields bending space-time, or virtual machines playing */ /* with time ) */ /* So.. you need to measure time, but with respect to a normal */ /* space-time. So.. we deal with this by calling for time from another */ /* machine, but do so with a very similar interface to that of */ /* gettimeofday(). */ /* To activate this, one only needs to set an environmental variable. */ /* Example: setenv IOZ_PIT hostname_of_PIT_server */ /* The environmental variable tells this client where to go to get */ /* correct timeofday time stamps, with the usual gettimeofday() */ /* resolution. (microsecond resolution) */ /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* The PIT client: Adapted from source found on the web for someone's */ /* daytime client code. (Used in many examples for network programming */ /* Reads PIT info over a socket from a PIT server. */ /* The PIT server sends its raw microsecond version of gettimeofday */ /* The PIT client converts this back into timeval structure format. */ /* Written by: Don Capps. [ capps@iozone.org ] */ /*----------------------------------------------------------------------*/ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /* >>>> DON'T forget, you must put a definition for PIT <<<<<<<<<< */ /* >>>> in /etc/services <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */ #define DFLT_SERVICE "PIT" /* Default service name. */ #define INVALID_DESC -1 /* Invalid file (socket) descriptor. */ #define MAXBFRSIZE 256 /* Max bfr sz to read remote TOD. */ /* ** Type definitions (for convenience). */ #if defined(Windows) int false = 0; int true = 1; #else typedef enum { false = 0, true } boolean; #endif typedef struct sockaddr_in sockaddr_in_t; typedef struct sockaddr_in6 sockaddr_in6_t; /* * Routine to mimic gettimeofday() using a remote PIT server */ #if defined(_SUA_) struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif int pit_gettimeofday( struct timeval *tp, struct timezone *foo, char *pit_hostname, char *pit_service) { int sckt; /* socket descriptor */ unsigned scopeId = 0; /* See if the interdimensional rift is active */ if(pit_hostname[0] == 0) { return gettimeofday(tp,foo); } if ( ( sckt = openSckt( pit_hostname, pit_service, scopeId ) ) == INVALID_DESC ) { fprintf( stderr, "Sorry... a connectionless socket could " "not be set up.\n"); return -1; } /* ** Get the remote PIT. */ pit( sckt ,tp ); close(sckt); return 0; } /* * Opens a socket for the PIT to use to get the time * from a remote time server ( A PIT server ) */ static int openSckt( const char *host, const char *service, unsigned int scopeId ) { struct addrinfo *ai; int aiErr; struct addrinfo *aiHead; struct addrinfo hints; sockaddr_in6_t *pSadrIn6; int sckt; /* * Initialize the 'hints' structure for getaddrinfo(3). */ memset( &hints, 0, sizeof( hints ) ); hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 records */ hints.ai_socktype = SOCK_STREAM; /* Connection oriented communication.*/ hints.ai_protocol = IPPROTO_TCP; /* TCP transport layer protocol only. */ /* ** Look up the host/service information. */ if ( ( aiErr = getaddrinfo( host, service, &hints, &aiHead ) ) != 0 ) { fprintf( stderr, "(line %d): ERROR - %s.\n", __LINE__, gai_strerror( aiErr ) ); return INVALID_DESC; } /* ** Go through the list and try to open a connection. Continue until either ** a connection is established or the entire list is exhausted. */ for ( ai = aiHead, sckt = INVALID_DESC; ( ai != NULL ) && ( sckt == INVALID_DESC ); ai = ai->ai_next ) { /* ** IPv6 kluge. Make sure the scope ID is set. */ if ( ai->ai_family == PF_INET6 ) { pSadrIn6 = (sockaddr_in6_t*) ai->ai_addr; if ( pSadrIn6->sin6_scope_id == 0 ) { pSadrIn6->sin6_scope_id = scopeId; } /* End IF the scope ID wasn't set. */ } /* End IPv6 kluge. */ /* ** Create a socket. */ sckt = socket( ai->ai_family, ai->ai_socktype, ai->ai_protocol ); if(sckt == -1) { sckt = INVALID_DESC; continue; /* Try the next address record in the list. */ } /* ** Set the target destination for the remote host on this socket. That ** is, this socket only communicates with the specified host. */ if (connect( sckt, ai->ai_addr, ai->ai_addrlen ) ) { (void) close( sckt ); /* Could use system call again here, but why? */ sckt = INVALID_DESC; continue; /* Try the next address record in the list. */ } } /* End FOR each address record returned by getaddrinfo(3). */ /* ** Clean up & return. */ freeaddrinfo( aiHead ); return sckt; } /* End openSckt() */ /* * Read the PIT, and convert this back into timeval * info, and store it in the timeval structure that was * passed in. */ static void pit( int sckt, struct timeval *tp) { char bfr[ MAXBFRSIZE+1 ]; int inBytes; long long value; /* ** Send a datagram to the server to wake it up. The content isn't ** important, but something must be sent to let it know we want the TOD. */ junk=write( sckt, "Are you there?", 14 ); /* ** Read the PIT from the remote host. */ inBytes = read( sckt, bfr, MAXBFRSIZE ); bfr[ inBytes ] = '\0'; /* Null-terminate the received string. */ /* * Convert result to timeval structure format */ sscanf(bfr,"%llu\n",&value); tp->tv_sec = (long)(value / 1000000); tp->tv_usec = (long)(value % 1000000); } /* sync does not exist in SUA */ #if defined(_SUA_) sync() { } #endif #define BUCKETS 40 long long buckets[BUCKETS]; long long bucket_val[BUCKETS] = { 20,40,60,80,100, 200,400,600,800,1000, 2000,4000,6000,8000,10000, 12000,14000,16000,18000,20000, 40000,60000,80000,100000, 200000,400000,600000,800000,1000000, 2000000,4000000,6000000,8000000,10000000, 20000000,30000000,60000000,90000000,120000000,120000001}; /* * Buckets: (Based on a Netapp internal consensus) * 0 1 2 3 4 * <=20us <=40us <=60us <=80us <=100us * * 5 6 7 8 9 * <=200us <=400us <=600us <=88us <=1ms * * 10 11 12 13 14 * <=2ms <=4ms <=6ms <=8ms <=10ms * * 15 16 17 18 19 * <=12ms <=14ms <=16ms <=18ms <=20ms * * 20 21 22 23 24 * <=20ms <=40ms <=60ms <=80ms <=100ms * * 25 26 27 28 29 * <=200ms <=400ms <=600ms <=800ms <=1s * * 30 31 32 33 34 * <=2s <=4s <=6s <=8s <=10s * * 35 36 37 38 39 * <=20s <=30s <=60 <=90s >90 */ /* fp=fopen("/tmp/iozone_latency_summary.txt","a"); dump_hist(fp); */ void hist_insert(double my_value) { int k; long long value; /* Convert to micro-seconds */ value = (long long)(my_value * 1000000); for(k=0;k bucket_val[k]) { buckets[k]++; break; } } } } void dump_hist(char *what,int id) { FILE *fp; char name[256]; sprintf(name,"%s_child_%d.txt","Iozone_histogram",id); fp = fopen(name,"a"); #ifndef NO_PRINT_LLD fprintf(fp,"Child: %d Op: %s\n",id,what); fprintf(fp,"Band 1: "); fprintf(fp," 20us:%-7.1lld ",buckets[0]); fprintf(fp," 40us:%-7.1lld ",buckets[1]); fprintf(fp," 60us:%-7.1lld ",buckets[2]); fprintf(fp," 80us:%-7.1lld ",buckets[3]); fprintf(fp,"100us:%-7.1lld \n",buckets[4]); fprintf(fp,"Band 2: "); fprintf(fp,"200us:%-7.1lld ",buckets[5]); fprintf(fp,"400us:%-7.1lld ",buckets[6]); fprintf(fp,"600us:%-7.1lld ",buckets[7]); fprintf(fp,"800us:%-7.1lld ",buckets[8]); fprintf(fp," 1ms:%-7.1lld \n",buckets[9]); fprintf(fp,"Band 3: "); fprintf(fp," 2ms:%-7.1lld ",buckets[10]); fprintf(fp," 4ms:%-7.1lld ",buckets[11]); fprintf(fp," 6ms:%-7.1lld ",buckets[12]); fprintf(fp," 8ms:%-7.1lld ",buckets[13]); fprintf(fp," 10ms:%-7.1lld \n",buckets[14]); fprintf(fp,"Band 4: "); fprintf(fp," 12ms:%-7.1lld ",buckets[15]); fprintf(fp," 14ms:%-7.1lld ",buckets[16]); fprintf(fp," 16ms:%-7.1lld ",buckets[17]); fprintf(fp," 18ms:%-7.1lld ",buckets[18]); fprintf(fp," 20ms:%-7.1lld \n",buckets[19]); fprintf(fp,"Band 5: "); fprintf(fp," 40ms:%-7.1lld ",buckets[20]); fprintf(fp," 60ms:%-7.1lld ",buckets[21]); fprintf(fp," 80ms:%-7.1lld ",buckets[22]); fprintf(fp,"100ms:%-7.1lld \n",buckets[23]); fprintf(fp,"Band 6: "); fprintf(fp,"200ms:%-7.1lld ",buckets[24]); fprintf(fp,"400ms:%-7.1lld ",buckets[25]); fprintf(fp,"600ms:%-7.1lld ",buckets[26]); fprintf(fp,"800ms:%-7.1lld ",buckets[27]); fprintf(fp," 1s:%-7.1lld \n",buckets[28]); fprintf(fp,"Band 7: "); fprintf(fp," 2s:%-7.1lld ",buckets[29]); fprintf(fp," 4s:%-7.1lld ",buckets[30]); fprintf(fp," 6s:%-7.1lld ",buckets[31]); fprintf(fp," 8s:%-7.1lld ",buckets[32]); fprintf(fp," 10s:%-7.1lld \n",buckets[33]); fprintf(fp,"Band 8: "); fprintf(fp," 20s:%-7.1lld ",buckets[34]); fprintf(fp," 40s:%-7.1lld ",buckets[35]); fprintf(fp," 60s:%-7.1lld ",buckets[36]); fprintf(fp," 80s:%-7.1lld ",buckets[37]); fprintf(fp," 120s:%-7.1lld \n",buckets[38]); fprintf(fp,"Band 9: "); fprintf(fp,"120+s:%-7.1lld \n\n",buckets[39]); #else fprintf(fp,"Child: %d Op: %s\n",id,what); fprintf(fp,"Band 1: "); fprintf(fp," 20us:%-7.1ld ",buckets[0]); fprintf(fp," 40us:%-7.1ld ",buckets[1]); fprintf(fp," 60us:%-7.1ld ",buckets[2]); fprintf(fp," 80us:%-7.1ld ",buckets[3]); fprintf(fp,"100us:%-7.1ld \n",buckets[4]); fprintf(fp,"Band 2: "); fprintf(fp,"200us:%-7.1ld ",buckets[5]); fprintf(fp,"400us:%-7.1ld ",buckets[6]); fprintf(fp,"600us:%-7.1ld ",buckets[7]); fprintf(fp,"800us:%-7.1ld ",buckets[8]); fprintf(fp," 1ms:%-7.1ld \n",buckets[9]); fprintf(fp,"Band 3: "); fprintf(fp," 2ms:%-7.1ld ",buckets[10]); fprintf(fp," 4ms:%-7.1ld ",buckets[11]); fprintf(fp," 6ms:%-7.1ld ",buckets[12]); fprintf(fp," 8ms:%-7.1ld ",buckets[13]); fprintf(fp," 10ms:%-7.1ld \n",buckets[14]); fprintf(fp,"Band 4: "); fprintf(fp," 12ms:%-7.1ld ",buckets[15]); fprintf(fp," 14ms:%-7.1ld ",buckets[16]); fprintf(fp," 16ms:%-7.1ld ",buckets[17]); fprintf(fp," 18ms:%-7.1ld ",buckets[18]); fprintf(fp," 20ms:%-7.1ld \n",buckets[19]); fprintf(fp,"Band 5: "); fprintf(fp," 40ms:%-7.1ld ",buckets[20]); fprintf(fp," 60ms:%-7.1ld ",buckets[21]); fprintf(fp," 80ms:%-7.1ld ",buckets[22]); fprintf(fp,"100ms:%-7.1ld \n",buckets[23]); fprintf(fp,"Band 6: "); fprintf(fp,"200ms:%-7.1ld ",buckets[24]); fprintf(fp,"400ms:%-7.1ld ",buckets[25]); fprintf(fp,"600ms:%-7.1ld ",buckets[26]); fprintf(fp,"800ms:%-7.1ld ",buckets[27]); fprintf(fp," 1s:%-7.1ld \n",buckets[28]); fprintf(fp,"Band 7: "); fprintf(fp," 2s:%-7.1ld ",buckets[29]); fprintf(fp," 4s:%-7.1ld ",buckets[30]); fprintf(fp," 6s:%-7.1ld ",buckets[31]); fprintf(fp," 8s:%-7.1ld ",buckets[32]); fprintf(fp," 10s:%-7.1ld \n",buckets[33]); fprintf(fp,"Band 8: "); fprintf(fp," 20s:%-7.1ld ",buckets[34]); fprintf(fp," 40s:%-7.1ld ",buckets[35]); fprintf(fp," 60s:%-7.1ld ",buckets[36]); fprintf(fp," 80s:%-7.1ld ",buckets[37]); fprintf(fp," 120s:%-7.1ld \n",buckets[38]); fprintf(fp,"Band 9: "); fprintf(fp,"120+s:%-7.1ld \n\n",buckets[39]); #endif fclose(fp); } #ifdef HAVE_ANSIC_C void * thread_fwrite_test(int x) #else void * thread_fwrite_test( x) #endif { struct child_stats *child_stat; double starttime1 = 0; double temp_time; double hist_time; double desired_op_rate_time; double actual_rate; double walltime, cputime; double compute_val = (double)0; float delay = (float)0; double thread_qtime_stop,thread_qtime_start; off64_t traj_offset; long long w_traj_bytes_completed; long long w_traj_ops_completed; FILE *w_traj_fd; int fd; long long recs_per_buffer; long long stopped,i; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long xx,xx2; char *dummyfile [MAXSTREAMS]; /* name of dummy file */ char *nbuff; char *maddr; char *wmaddr,*free_addr; char now_string[30]; int anwser,bind_cpu,wval; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif off64_t filebytes64; char tmpname[256]; FILE *thread_wqfd; FILE *thread_Lwqfd; char *filename; char *stdio_buf; char *how; long long Index = 0; FILE *stream = NULL; int First_Run[MAXSTREAMS]; int kk; for(kk=0;kkthroughput = 0; child_stat->actual = 0; child_stat->flag=CHILD_STATE_READY; /* Tell parent child is ready to go */ if(distributed && client_iozone) tell_master_ready(chid); if(distributed && client_iozone) { if(cdebug) { printf("Child %d waiting for go from master\n",(int)xx); fflush(stdout); } wait_for_master_go(chid); if(cdebug) { printf("Child %d received go from master\n",(int)xx); fflush(stdout); } } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } written_so_far=0; child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->actual = 0; child_stat->throughput = 0; stopped=0; if(Q_flag) { sprintf(tmpname,"Child_%d_fwol.dat",(int)xx); thread_wqfd=fopen(tmpname,"a"); if(thread_wqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_wqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","fwrite test start: ",now_string); } starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } /*******************************************************************/ for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; buffer = mbuffer + Index; } if((verify & diag_v) || dedup_flag || dedup_iflag) fill_buffer(buffer,reclen,(long long)pattern,sverify,i); if(purge) purgeit(buffer,reclen); if(Q_flag || hist_summary || op_rate_flag) { thread_qtime_start=time_so_far(); } if(fwrite(buffer, (size_t) reclen, 1, stream) != 1) { #ifdef NO_PRINT_LLD printf("\nError fwriting block %ld, fd= %d\n", i, fd); #else printf("\nError fwriting block %lld, fd= %d\n", i, fd); #endif perror("fwrite"); exit_code = 74; signal_handler(); } #ifndef NO_THREADS count_burst(&burst_acc_time_sec, xx); #endif if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); if( actual_rate < desired_op_rate_time) my_unap((unsigned long long)((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_wqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_wqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } w_traj_ops_completed++; w_traj_bytes_completed+=reclen; written_so_far+=reclen/1024; } if(include_flush) { fflush(stream); wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } } if(include_close) { wval=fclose(stream); if(wval==-1){ perror("fclose"); signal_handler(); } } /*******************************************************************/ if(!stopped){ temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec); else child_stat->throughput = ((temp_time - starttime1)-time_res - burst_acc_time_sec) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; } if(cdebug) { printf("Child %d: throughput %f actual %f \n",(int)chid, child_stat->throughput, child_stat->actual); fflush(stdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_FWRITE_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); if (debug1) { #ifdef NO_PRINT_LLD printf(" child/slot: %ld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n", (long)xx, #else printf(" child/slot: %lld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n",(long long)xx, #endif walltime, cputime,cpu_util(cputime, walltime)); } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ stopped=0; /*******************************************************************/ /* End fwrite performance test. *************************************/ /*******************************************************************/ if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(Q_flag && (thread_wqfd !=0) ) fclose(thread_wqfd); free(dummyfile[xx]); if(w_traj_flag) fclose(w_traj_fd); if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Fwrite test finished: ",now_string); fclose(thread_Lwqfd); } /*******************************************************************/ if(!include_close) { wval=fflush(stream); if(wval==-1){ perror("fflush"); signal_handler(); } wval=fsync(fd); if(wval==-1){ perror("fsync"); signal_handler(); } wval=fclose(stream); if(wval==-1){ perror("fclose"); signal_handler(); } } if(restf) sleep((int)(int)rest_val); free(stdio_buf); if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } /*******************************************************************/ if(hist_summary) dump_hist("Fwrite",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } #ifdef HAVE_ANSIC_C void * thread_fread_test(int x) #else void * thread_fread_test( x) #endif { struct child_stats *child_stat; double starttime1 = 0; double temp_time; double hist_time; double desired_op_rate_time; double actual_rate; double walltime, cputime; double compute_val = (double)0; float delay = (float)0; double thread_qtime_stop,thread_qtime_start; off64_t traj_offset; long long w_traj_bytes_completed; long long w_traj_ops_completed; FILE *w_traj_fd; int fd; long long recs_per_buffer; long long stopped,i; off64_t written_so_far, read_so_far, re_written_so_far,re_read_so_far; long long xx,xx2; char *dummyfile [MAXSTREAMS]; /* name of dummy file */ char *nbuff; char *maddr; char *wmaddr,*free_addr; char now_string[30]; int anwser,bind_cpu; #if defined(VXFS) || defined(solaris) int test_foo = 0; #endif off64_t filebytes64; char tmpname[256]; FILE *thread_wqfd; FILE *thread_Lwqfd; if(compute_flag) delay=compute_time; nbuff=maddr=wmaddr=free_addr=0; thread_qtime_stop=thread_qtime_start=0; thread_wqfd=w_traj_fd=thread_Lwqfd=(FILE *)0; traj_offset=walltime=cputime=0; anwser=bind_cpu=0; char *stdio_buf; long long Index = 0; FILE *stream = NULL; char *filename; if(w_traj_flag) { filebytes64 = w_traj_fsize; numrecs64=w_traj_ops; } else { filebytes64 = numrecs64*reclen; } written_so_far=read_so_far=re_written_so_far=re_read_so_far=0; w_traj_bytes_completed=w_traj_ops_completed=0; recs_per_buffer = cache_size/reclen ; #ifdef NO_THREADS xx=chid; #else if(use_thread) { xx = (long long)((long)x); } else { xx=chid; } #endif #ifndef NO_THREADS #ifdef _HPUX_SOURCE if(ioz_processor_bind) { bind_cpu=(begin_proc+(int)xx)%num_processors; pthread_processor_bind_np(PTHREAD_BIND_FORCED_NP, (pthread_spu_t *)&anwser, (pthread_spu_t)bind_cpu, pthread_self()); my_nap(40); /* Switch to new cpu */ } #endif #endif if(use_thread) nbuff=barray[xx]; else nbuff=buffer; if(debug1 ) { if(use_thread) #ifdef NO_PRINT_LLD printf("\nStarting child %ld\n",(long)xx); #else printf("\nStarting child %lld\n",(long long)xx); #endif else #ifdef NO_PRINT_LLD printf("\nStarting process %d slot %ld\n",getpid(),(long)xx); #else printf("\nStarting process %d slot %lld\n",getpid(),(long long)xx); #endif } dummyfile[xx]=(char *)malloc((size_t)MAXNAMESIZE); xx2=xx; if(share_file) xx2=(long long)0; if(mfflag) { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s",filearray[xx2]); #else sprintf(dummyfile[xx],"%s",filearray[xx2]); #endif } else { #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],xx2); #endif } filename=dummyfile[xx]; if(mmapflag || async_flag) return(0); stdio_buf=(char *)malloc((size_t)reclen); if(Uflag) /* Unmount and re-mount the mountpoint */ { purge_buffer_cache(); } #ifdef IRIX64 if((stream=(FILE *)fopen(filename,"r")) == 0) { printf("\nCan not fdopen temp file: %s\n", filename); perror("fdopen"); exit(51); } #else if((stream=(FILE *)I_FOPEN(filename,"r")) == 0) { printf("\nCan not fdopen temp file: %s\n", filename); perror("fdopen"); exit(52); } #endif fd=I_OPEN(filename,O_RDONLY,0); fsync(fd); close(fd); if(direct_flag) setvbuf(stream,stdio_buf,_IONBF,reclen); else setvbuf(stream,stdio_buf,_IOFBF,reclen); if(use_thread) buffer=nbuff; else buffer=mainbuffer; if(fetchon) fetchit(buffer,reclen); compute_val=(double)0; /*******************************************************************/ /*******************************************************************/ child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->throughput = 0; child_stat->actual = 0; child_stat->flag=CHILD_STATE_READY; /* Tell parent child is ready to go */ if(distributed && client_iozone) tell_master_ready(chid); if(distributed && client_iozone) { if(cdebug) { printf("Child %d waiting for go from master\n",(int)xx); fflush(stdout); } wait_for_master_go(chid); if(cdebug) { printf("Child %d received go from master\n",(int)xx); fflush(stdout); } } else { while(child_stat->flag!=CHILD_STATE_BEGIN) /* Wait for signal from parent */ Poll((long long)1); } written_so_far=0; child_stat = (struct child_stats *)&shmaddr[xx]; child_stat->actual = 0; child_stat->throughput = 0; stopped=0; if(Q_flag) { sprintf(tmpname,"Child_%d_frol.dat",(int)xx); thread_wqfd=fopen(tmpname,"a"); if(thread_wqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } fprintf(thread_wqfd,"Offset in kBytes Latency in microseconds Transfer size in bytes\n"); } if(L_flag) { sprintf(tmpname,"Child_%d.log",(int)xx); thread_Lwqfd=fopen(tmpname,"a"); if(thread_Lwqfd==0) { client_error=errno; if(distributed && client_iozone) send_stop(); printf("Unable to open %s\n",tmpname); exit(40); } get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","fread test start: ",now_string); } starttime1 = time_so_far(); if(cpuutilflag) { walltime = starttime1; cputime = cputime_so_far(); } /*******************************************************************/ for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; buffer = mbuffer + Index; } if(purge) purgeit(buffer,reclen); if(Q_flag || hist_summary || op_rate_flag) { thread_qtime_start=time_so_far(); } if(fread(buffer, (size_t) reclen,1, stream) != 1) { #ifdef _64BIT_ARCH_ #ifdef NO_PRINT_LLD printf("\nError freading block %ld %x\n", (long)i, (unsigned long)buffer); #else printf("\nError freading block %lld %llx\n", (long long)i, (unsigned long long)buffer); #endif #else #ifdef NO_PRINT_LLD printf("\nError freading block %ld %lx\n", (long)i, (long)buffer); #else printf("\nError freading block %lld %lx\n", (long long)i, (long)buffer); #endif #endif perror("read"); exit(54); } if(verify){ if(verify_buffer(buffer,reclen,(off64_t)i,reclen,(long long)pattern,sverify)){ exit(55); } } if(hist_summary) { thread_qtime_stop=time_so_far(); hist_time =(thread_qtime_stop-thread_qtime_start); hist_insert(hist_time); } if(op_rate_flag) { thread_qtime_stop=time_so_far(); desired_op_rate_time = ((double)1.0/(double)op_rate); actual_rate = (double)(thread_qtime_stop-thread_qtime_start); if( actual_rate < desired_op_rate_time) my_unap((unsigned long long)((desired_op_rate_time-actual_rate)*1000000.0 )); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_wqfd,"%10.1ld %10.0f %10.1ld\n",(long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long)reclen); #else fprintf(thread_wqfd,"%10.1lld %10.0f %10.1lld\n",(long long)(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,(long long)reclen); #endif } w_traj_ops_completed++; w_traj_bytes_completed+=reclen; written_so_far+=reclen/1024; } if(include_flush) fflush(stream); if(include_close) { fclose(stream); } /*******************************************************************/ if(!stopped){ temp_time = time_so_far(); if(inc_think) child_stat->throughput = ((temp_time - starttime1)-time_res); else child_stat->throughput = ((temp_time - starttime1)-time_res) -compute_val; if(child_stat->throughput < (double).000001) { child_stat->throughput= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(OPS_flag){ /*written_so_far=(written_so_far*1024)/reclen;*/ written_so_far=w_traj_ops_completed; } child_stat->throughput = (double)written_so_far/child_stat->throughput; child_stat->actual = (double)written_so_far; } if(cdebug) { printf("Child %d: throughput %f actual %f \n",(int)chid, child_stat->throughput, child_stat->actual); fflush(stdout); } if(cpuutilflag) { cputime = cputime_so_far() - cputime; if (cputime < cputime_res) cputime = 0.0; child_stat->cputime = cputime; walltime = time_so_far() - walltime; child_stat->walltime = walltime; } if(distributed && client_iozone) tell_master_stats(THREAD_FREAD_TEST, chid, child_stat->throughput, child_stat->actual, child_stat->cputime, child_stat->walltime, (char)*stop_flag, (long long)CHILD_STATE_HOLD); if (debug1) { #ifdef NO_PRINT_LLD printf(" child/slot: %ld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n",(long)xx, #else printf(" child/slot: %lld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n",(long long)xx, #endif walltime, cputime,cpu_util(cputime, walltime)); } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ stopped=0; /*******************************************************************/ /* End fead performance test. *************************************/ /*******************************************************************/ if(debug1) #ifdef NO_PRINT_LLD printf("\nChild finished %ld\n",(long)xx); #else printf("\nChild finished %lld\n",(long long)xx); #endif if(Q_flag && (thread_wqfd !=0) ) fclose(thread_wqfd); free(dummyfile[xx]); if(w_traj_flag) fclose(w_traj_fd); if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Fread test finished: ",now_string); fclose(thread_Lwqfd); } /*******************************************************************/ if(!include_close) { fflush(stream); fclose(stream); } stream = NULL; if(restf) sleep((int)(int)rest_val); free(stdio_buf); if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } /*******************************************************************/ if(hist_summary) dump_hist("Fread",(int)xx); if(distributed && client_iozone) return(0); #ifdef NO_THREADS exit(0); #else if(use_thread) thread_exit(); else exit(0); #endif return(0); } static void update_burst_sleep(int fd, long long reclen, double *burst_sleep_time_till_now) { if (burst_size_kb_64 == -1 || burst_sleep_duration_msec == -1) return; written_this_burst += reclen; if (written_this_burst >= (burst_size_kb_64 * 1024)) { struct timespec req, rem; int err; double sleep_start_time; written_this_burst = 0; rem.tv_sec = burst_sleep_duration_msec/1000; rem.tv_nsec = (burst_sleep_duration_msec%1000)*1000000; fsync(fd); sleep_start_time = time_so_far(); do { req = rem; err = nanosleep(&req, &rem); } while ((err == -1) && (errno == EINTR)); *burst_sleep_time_till_now += (time_so_far() - sleep_start_time); } } #ifndef NO_THREADS static void count_burst(double* burst_acc_time_sec, long long stream_id) { double burst_start_time_sec; struct timespec req, rem; int err; if (burst_size_per_child == 0 || burst_sleep_duration_msec == -1) return; /* Burst mode is handled */ burst_written_so_far[stream_id] += reclen; /* Need to sleep to empty the burst buffer ? */ if (burst_size_per_child <= burst_written_so_far[stream_id]) { burst_written_so_far[stream_id] = 0; if (!direct_flag) { fsync(fd); } /* Wait for other threads*/ burst_start_time_sec = time_so_far(); pthread_barrier_wait(barrier); /* Sleep to empty the burst buffer*/ rem.tv_sec = burst_sleep_duration_msec/1000; rem.tv_nsec = (burst_sleep_duration_msec%1000)*1000000; do { req = rem; err = nanosleep(&req, &rem); } while ((err == -1) && (errno == EINTR)); *burst_acc_time_sec += time_so_far() - burst_start_time_sec; } } #endif #ifdef NO_FORK pid_t no_fork(void) { printf("Fork not supported\n"); return(-1); } #endif #ifdef NO_SOCKET int no_socket(int x, int y, int z) { printf("Socket() not supported\n"); return(-1); } int no_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { printf("Accept() not supported\n"); return(-1); } int no_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) { printf("Bind() not supported\n"); return(-1); } int no_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) { printf("Connect() not supported\n"); return(-1); } #endif #ifdef NO_SIGNAL int no_kill(pid_t pid, int sig) { printf("Kill() not supported\n"); return(-1); } #endif /* * * Used to touch all of the buffers so that the CPU data * * cache is hot, and not part of the measurement. * */ void touch_dedup(char *i, int size) { register int x; register int *ip; if(N_special) { new_touch_dedup(i, size); return; } ip = (int *)i; srand(DEDUPSEED); for(x=0;x<(int)(size/sizeof(int));x++) { *ip=rand(); /* fill initial buffer */ ip++; } } /* * As quickly as possible, generate a new buffer that * can not be easily compressed, or de-duped. Also * permit specified percentage of buffer to be updated. * * ibuf ... input buffer * obuf ... output buffer * seed ... Seed to use for srand, rand -> xor ops * Seed composed from: blocknumber (do not include childnum as you want duplicates) * size ... size of buffers. (in bytes) * percent. Percent of buffer to modify. * percent_interior. Percent of buffer that is dedupable within * and across files * percent_compress. Percent of buffer that is dedupable within * but not across files * * Returns 0 (zero) for success, and -1 (minus one) for failure. */ int gen_new_buf(char *ibuf, char *obuf, long seed, int size, int percent, int percent_interior, int percent_compress, int all) { register int *ip, *op; /* Register for speed */ register int iseed; /* Register for speed */ register int isize; /* Register for speed */ register int cseed; /* seed for dedupable for within & ! across */ register int x,w; /* Register for speed */ register int value; /* Register for speed */ register int interior_size; /* size of interior dedup region */ register int compress_size; /* size of compression dedup region */ int ret = 0; if(N_special) { ret = special_gen_new_buf(ibuf, obuf, seed, size, percent, percent_interior, percent_compress, all); return(ret); } if(ibuf == NULL) /* no input buf */ return(-1); if(obuf == NULL) /* no output buf */ return(-1); if((percent > 100) || (percent < 0)) /* percent check */ return(-1); if(size == 0) /* size check */ return(-1); srand(seed+1+(((int)numrecs64)*dedup_mseed)); /* set random seed */ iseed = rand(); /* generate random value */ isize = (size * percent)/100; /* percent that is dedupable */ interior_size = ((isize * percent_interior)/100);/* /sizeof(int) */ compress_size =((interior_size * percent_compress)/100); ip = (int *)ibuf; /* pointer to input buf */ op = (int *)obuf; /* pointer to output buf */ if(all == 0) /* Special case for verify only */ isize = sizeof(int); /* interior_size = dedup_within + dedup_across */ for(w=0;w 0) { srand(1+seed+((chid+chid_skew+1)*(int)numrecs64)*dedup_mseed); value=rand(); /* printf("Non-dedup value %x seed %x\n",value,seed);*/ for( ; x, 2005-10-31 # # This script is based loosely on the Generate_Graph set # of scripts that come with iozone, but is a complete re-write # # The main reason to write this was the need to compare the behaviour of # two or more different setups, for tuning filesystems or # comparing different pieces of hardware. # # This script is in the public domain, too short and too trivial # to deserve a copyright. # # Simply run iozone like, for example, ./iozone -a -g 4G > config1.out (if your machine has 4GB) # and then run perl report.pl config1.out # or get another report from another box into config2.out and run # perl report.pl config1.out config2.out # the look in the report_* directory for .png # # If you don't like png or the graphic size, search for "set terminal" in this file and put whatever gnuplot # terminal you want. Note I've also noticed that gnuplot switched the set terminal png syntax # a while back, you might need "set terminal png small size 900,700" # @Reports=@ARGV; die "usage: $0 [...]\n" if not @Reports or grep (m|^-|, @Reports); die "report files must be in current directory" if grep (m|/|, @Reports); %columns=( 'write' =>3, 'read' =>5, 'rewrite' =>4, 'reread' =>6, 'randread' =>7, 'randwrite' =>8, 'bkwdread' =>9, 'recrewrite'=>10, 'strideread'=>11, 'fwrite' =>12, 'frewrite' =>13, 'fread' =>14, 'freread' =>15, ); # # create output directory. the name is the concatenation # of all report file names (minus the file extension, plus # prefix report_) # $outdir="report_".join("_",map{/([^\.]+)(\..*)?/ && $1}(@Reports)); print STDERR "Output directory: $outdir "; if ( -d $outdir ) { print STDERR "(removing old directory) "; system "rm -rf $outdir"; } mkdir $outdir or die "cannot make directory $outdir"; print STDERR "done.\nPreparing data files..."; foreach $report (@Reports) { open(I, $report) or die "cannot open $report for reading"; $report=~/^([^\.]+)/; $datafile="$1.dat"; push @datafiles, $datafile; open(O, ">$outdir/$datafile") or die "cannot open $outdir/$datafile for writing"; open(O2, ">$outdir/2d-$datafile") or die "cannot open $outdir/$datafile for writing"; while() { next unless ( /^[\s\d]+$/ ); @split = split(); next unless ( @split >= 8 ); print O; print O2 if $split[1] == 16384 or $split[0] == $split[1]; } close I, O, O2; } print STDERR "done.\nGenerating graphs:"; foreach $column (keys %columns) { print STDERR " $column"; open(G, ">$outdir/$column.do") or die "cannot open $outdir/$column.do for writing"; print G qq{ set title "Iozone performance: $column" set grid lt 2 lw 1 set surface set parametric set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z #set xrange [2.**5:2.**24] set xlabel "File size in Kbytes" set ylabel "Record size in Kbytes" set zlabel "Kbytes/sec" set style data lines set dgrid3d 80,80,3 #set terminal png small picsize 900 700 set terminal png small size 900 700 set output "$column.png" }; print G "splot ". join(", ", map{qq{"$_" using 1:2:$columns{$column} title "$_"}}(@datafiles)); print G "\n"; close G; open(G, ">$outdir/2d-$column.do") or die "cannot open $outdir/$column.do for writing"; print G qq{ set title "Iozone performance: $column" #set terminal png small picsize 450 350 set terminal png small size 450 350 set logscale x set xlabel "File size in Kbytes" set ylabel "Kbytes/sec" set output "2d-$column.png" }; print G "plot ". join(", ", map{qq{"2d-$_" using 1:$columns{$column} title "$_" with lines}}(@datafiles)); print G "\n"; close G; if ( system("cd $outdir && gnuplot $column.do && gnuplot 2d-$column.do") ) { print STDERR "(failed) "; } else { print STDERR "(ok) "; } } print STDERR "done.\n"; iozone3_488/src/current/fileop.c0000444000175000017500000013526613573734166015772 0ustar cappscapps/* * Author: Don Capps * 3/13/2006 * * Author: Don Capps (capps@iozone.org) * 7417 Crenshaw * Plano, TX 75025 * * Copyright 2006, 2007, 2008, 2009 Don Capps. * * License to freely use and distribute this software is hereby granted * by the author, subject to the condition that this copyright notice * remains intact. The author retains the exclusive right to publish * derivative works based on this work, including, but not limited to, * revised versions of this work", * * fileop [-f X ]|[-l # -u #] [-s Y] [-e] [-b] [-w] [-d ] [-t] [-v] [-h] -f # Force factor. X^3 files will be created and removed. -l # Lower limit on the value of the Force factor. -u # Upper limit on the value of the Force factor. -s # Optional. Sets filesize for the create/write. May use suffix 'K' or 'M'. -e Excel importable format. -b Output best case. -w Output worst case. -d Specify starting directory. -U Mount point to remount between tests. -t Verbose output option. -v Version information. -h Help text. * * X is a force factor. The total number of files will * be X * X * X ( X ^ 3 ) * The structure of the file tree is: * X number of Level 1 directories, with X number of * level 2 directories, with X number of files in each * of the level 2 directories. * * Example: fileop 2 * * dir_1 dir_2 * / \ / \ * sdir_1 sdir_2 sdir_1 sdir_2 * / \ / \ / \ / \ * file_1 file_2 file_1 file_2 file_1 file_2 file_1 file_2 * * Each file will be created, and then 1 byte is written to the file. * */ #include #include #include #include #include #include #include #include #include #include #include #if defined(Windows) #include #endif #if !defined(PATH_MAX) #define PATH_MAX 255 #endif #if defined(_SUA_) extern char *optarg; extern char *opterr; int fsync(); int getopt(); #endif int junk, *junkp; int x,excel; int verbose = 0; int sz = 1; char *mbuffer; int incr = 1; #define _STAT_CREATE 0 #define _STAT_WRITE 1 #define _STAT_CLOSE 2 #define _STAT_LINK 3 #define _STAT_UNLINK 4 #define _STAT_DELETE 5 #define _STAT_STAT 6 #define _STAT_ACCESS 7 #define _STAT_CHMOD 8 #define _STAT_READDIR 9 #define _STAT_DIR_CREATE 10 #define _STAT_DIR_DELETE 11 #define _STAT_READ 12 #define _STAT_OPEN 13 #define _STAT_DIR_TRAVERSE 14 #define _NUM_STATS 15 struct stat_struct { double starttime; double endtime; double speed; double best; double worst; double dummy; double total_time; double dummy1; long long counter; } volatile stats[_NUM_STATS]; static double time_so_far(void); void dir_create(int); void dir_traverse(int); void dir_delete(int); void file_create(int); void file_stat(int); void file_access(int); void file_chmod(int); void file_readdir(int); void file_delete(int); void file_link(int); void file_unlink(int); void file_read(int); void splash(void); void usage(void); void clear_stats(); int validate(char *, int , char ); #define THISVERSION " $Revision: 1.63 $" /*#define NULL 0*/ char version[]=THISVERSION; char thedir[PATH_MAX]="."; /* Default is to use the current directory */ const char *mountname=NULL; /* Default is not to unmount anything between the tests */ int cret; int lower, upper,range; int i; int best, worst; int dirlen; /************************************************************************/ /* Routine to purge the buffer cache by unmounting drive. */ /************************************************************************/ void purge_buffer_cache() { if (!mountname) return; char cwd[PATH_MAX]; char command[1024]; int ret,i; junkp=(int *)getcwd(cwd, sizeof(cwd)); junk=chdir("/"); strcpy(command,"umount "); strcat(command, mountname); /* umount might fail if the device is still busy, so retry unmounting several times with increasing delays */ for (i = 1; i < 10; ++i) { ret = system(command); if (ret == 0) break; sleep(i); /* seconds */ } strcpy(command,"mount "); strcat(command, mountname); junk=system(command); junk=chdir(cwd); } int main(int argc, char **argv) { if(argc == 1) { usage(); exit(1); } while((cret = getopt(argc,argv,"hbwetvf:s:l:u:d:U:i: ")) != EOF){ switch(cret){ case 'h': usage(); exit(0); break; case 'd' : dirlen=strlen(optarg); if (optarg[dirlen-1]=='/') --dirlen; strncpy(thedir, optarg, dirlen); thedir[dirlen] = 0; break; case 'U': mountname = optarg; break; case 'i': /* Increment force by */ incr=atoi(optarg); if(incr < 0) incr=1; break; case 'f': /* Force factor */ x=atoi(optarg); if(x < 0) x=1; break; case 's': /* Size of files */ sz=atoi(optarg); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ sz = (1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ sz = (1024 * 1024 * atoi(optarg)); } if(sz < 0) sz=1; break; case 'l': /* lower force value */ lower=atoi(optarg); range=1; if(lower < 0) lower=1; break; case 'v': /* version */ splash(); exit(0); break; case 'u': /* upper force value */ upper=atoi(optarg); range=1; if(upper < 0) upper=1; break; case 't': /* verbose */ verbose=1; break; case 'e': /* Excel */ excel=1; break; case 'b': /* Best */ best=1; break; case 'w': /* Worst */ worst=1; break; } } mbuffer=(char *)malloc(sz); memset(mbuffer,'a',sz); if(!excel) printf("\nFileop: Working in %s, File size is %d, Output is in Ops/sec. (A=Avg, B=Best, W=Worst)\n", thedir, sz); if(!verbose) { #ifdef Windows printf(" . %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %10s\n", "mkdir","chdir","rmdir","create","open","read","write","close","stat", "access","chmod","readdir","delete"," Total_files"); #else printf(" . %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %10s\n", "mkdir","chdir","rmdir","create","open", "read","write","close","stat", "access","chmod","readdir","link ","unlink","delete", " Total_files"); #endif } junk=chdir(thedir); /* change starting point */ if(x==0) x=1; if(range==0) lower=upper=x; for(i=lower;i<=upper;i+=incr) { clear_stats(); x=i; /* * Dir Create test */ purge_buffer_cache(); dir_create(x); if(verbose) { printf("mkdir: Dirs = %9lld ",stats[_STAT_DIR_CREATE].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_DIR_CREATE].total_time); printf(" Avg mkdir(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_DIR_CREATE].counter/stats[_STAT_DIR_CREATE].total_time, stats[_STAT_DIR_CREATE].total_time/stats[_STAT_DIR_CREATE].counter); printf(" Best mkdir(s)/sec = %12.2f (%12.9f seconds/op)\n",1/stats[_STAT_DIR_CREATE].best,stats[_STAT_DIR_CREATE].best); printf(" Worst mkdir(s)/sec = %12.2f (%12.9f seconds/op)\n\n",1/stats[_STAT_DIR_CREATE].worst,stats[_STAT_DIR_CREATE].worst); } /* * Dir Traverse test */ purge_buffer_cache(); dir_traverse(x); if(verbose) { printf("chdir: Dirs = %9lld ",stats[_STAT_DIR_TRAVERSE].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_DIR_TRAVERSE].total_time); printf(" Avg chdir(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_DIR_TRAVERSE].counter/stats[_STAT_DIR_TRAVERSE].total_time, stats[_STAT_DIR_TRAVERSE].total_time/stats[_STAT_DIR_TRAVERSE].counter); printf(" Best chdir(s)/sec = %12.2f (%12.9f seconds/op)\n",1/stats[_STAT_DIR_TRAVERSE].best,stats[_STAT_DIR_TRAVERSE].best); printf(" Worst chdir(s)/sec = %12.2f (%12.9f seconds/op)\n\n",1/stats[_STAT_DIR_TRAVERSE].worst,stats[_STAT_DIR_TRAVERSE].worst); } /* * Dir delete test */ purge_buffer_cache(); dir_delete(x); if(verbose) { printf("rmdir: Dirs = %9lld ",stats[_STAT_DIR_DELETE].counter); printf("Total Time = %12.9f seconds\n",stats[_STAT_DIR_DELETE].total_time); printf(" Avg rmdir(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_DIR_DELETE].counter/stats[_STAT_DIR_DELETE].total_time, stats[_STAT_DIR_DELETE].total_time/stats[_STAT_DIR_DELETE].counter); printf(" Best rmdir(s)/sec = %12.2f (%12.9f seconds/op)\n",1/stats[_STAT_DIR_DELETE].best,stats[_STAT_DIR_DELETE].best); printf(" Worst rmdir(s)/sec = %12.2f (%12.9f seconds/op)\n\n",1/stats[_STAT_DIR_DELETE].worst,stats[_STAT_DIR_DELETE].worst); } /* * Create test */ purge_buffer_cache(); file_create(x); if(verbose) { printf("create: Files = %9lld ",stats[_STAT_CREATE].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_CREATE].total_time); printf(" Avg create(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_CREATE].counter/stats[_STAT_CREATE].total_time, stats[_STAT_CREATE].total_time/stats[_STAT_CREATE].counter); printf(" Best create(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_CREATE].best,stats[_STAT_CREATE].best); printf(" Worst create(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_CREATE].worst,stats[_STAT_CREATE].worst); printf("write: Files = %9lld ",stats[_STAT_WRITE].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_WRITE].total_time); printf(" Avg write(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_WRITE].counter/stats[_STAT_WRITE].total_time, stats[_STAT_WRITE].total_time/stats[_STAT_WRITE].counter); printf(" Best write(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_WRITE].best,stats[_STAT_WRITE].best); printf(" Worst write(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_WRITE].worst,stats[_STAT_WRITE].worst); printf("close: Files = %9lld ",stats[_STAT_CLOSE].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_CLOSE].total_time); printf(" Avg close(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_CLOSE].counter/stats[_STAT_CLOSE].total_time, stats[_STAT_CLOSE].total_time/stats[_STAT_CLOSE].counter); printf(" Best close(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_CLOSE].best,stats[_STAT_CLOSE].best); printf(" Worst close(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_CLOSE].worst,stats[_STAT_CLOSE].worst); } /* * Stat test */ purge_buffer_cache(); file_stat(x); if(verbose) { printf("stat: Files = %9lld ",stats[_STAT_STAT].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_STAT].total_time); printf(" Avg stat(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_STAT].counter/stats[_STAT_STAT].total_time, stats[_STAT_STAT].total_time/stats[_STAT_STAT].counter); printf(" Best stat(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_STAT].best,stats[_STAT_STAT].best); printf(" Worst stat(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_STAT].worst,stats[_STAT_STAT].worst); } /* * Read test */ purge_buffer_cache(); file_read(x); if(verbose) { printf("open: Files = %9lld ",stats[_STAT_OPEN].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_OPEN].total_time); printf(" Avg open(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_OPEN].counter/stats[_STAT_OPEN].total_time, stats[_STAT_OPEN].total_time/stats[_STAT_OPEN].counter); printf(" Best open(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_OPEN].best,stats[_STAT_OPEN].best); printf(" Worst open(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_OPEN].worst,stats[_STAT_OPEN].worst); printf("read: Files = %9lld ",stats[_STAT_READ].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_READ].total_time); printf(" Avg read(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_READ].counter/stats[_STAT_READ].total_time, stats[_STAT_READ].total_time/stats[_STAT_READ].counter); printf(" Best read(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_READ].best,stats[_STAT_READ].best); printf(" Worst read(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_READ].worst,stats[_STAT_READ].worst); } /* * Access test */ purge_buffer_cache(); file_access(x); if(verbose) { printf("access: Files = %9lld ",stats[_STAT_ACCESS].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_ACCESS].total_time); printf(" Avg access(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_ACCESS].counter/stats[_STAT_ACCESS].total_time, stats[_STAT_ACCESS].total_time/stats[_STAT_ACCESS].counter); printf(" Best access(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_ACCESS].best,stats[_STAT_ACCESS].best); printf(" Worst access(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_ACCESS].worst,stats[_STAT_ACCESS].worst); } /* * Chmod test */ purge_buffer_cache(); file_chmod(x); if(verbose) { printf("chmod: Files = %9lld ",stats[_STAT_CHMOD].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_CHMOD].total_time); printf(" Avg chmod(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_CHMOD].counter/stats[_STAT_CHMOD].total_time, stats[_STAT_CHMOD].total_time/stats[_STAT_CHMOD].counter); printf(" Best chmod(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_CHMOD].best,stats[_STAT_CHMOD].best); printf(" Worst chmod(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_CHMOD].worst,stats[_STAT_CHMOD].worst); } /* * readdir test */ purge_buffer_cache(); file_readdir(x); if(verbose) { printf("readdir: Files = %9lld ",stats[_STAT_READDIR].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_READDIR].total_time); printf(" Avg readdir(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_READDIR].counter/stats[_STAT_READDIR].total_time, stats[_STAT_READDIR].total_time/stats[_STAT_READDIR].counter); printf(" Best readdir(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_READDIR].best,stats[_STAT_READDIR].best); printf(" Worst readdir(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_READDIR].worst,stats[_STAT_READDIR].worst); } #if !defined(Windows) /* * link test */ purge_buffer_cache(); file_link(x); if(verbose) { printf("link: Files = %9lld ",stats[_STAT_LINK].counter); printf("Total Time = %12.9f seconds\n",stats[_STAT_LINK].total_time); printf(" Avg link(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_LINK].counter/stats[_STAT_LINK].total_time, stats[_STAT_LINK].total_time/stats[_STAT_LINK].counter); printf(" Best link(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_LINK].best,stats[_STAT_LINK].best); printf(" Worst link(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_LINK].worst,stats[_STAT_LINK].worst); } /* * unlink test */ purge_buffer_cache(); file_unlink(x); if(verbose) { printf("unlink: Files = %9lld ",stats[_STAT_UNLINK].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_UNLINK].total_time); printf(" Avg unlink(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_UNLINK].counter/stats[_STAT_UNLINK].total_time, stats[_STAT_UNLINK].total_time/stats[_STAT_UNLINK].counter); printf(" Best unlink(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_UNLINK].best,stats[_STAT_UNLINK].best); printf(" Worst unlink(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_UNLINK].worst,stats[_STAT_UNLINK].worst); } #endif /* * Delete test */ purge_buffer_cache(); file_delete(x); if(verbose) { printf("delete: Files = %9lld ",stats[_STAT_DELETE].counter); printf("Total Time = %12.9f seconds\n", stats[_STAT_DELETE].total_time); printf(" Avg delete(s)/sec = %12.2f (%12.9f seconds/op)\n", stats[_STAT_DELETE].counter/stats[_STAT_DELETE].total_time, stats[_STAT_DELETE].total_time/stats[_STAT_DELETE].counter); printf(" Best delete(s)/sec = %12.2f (%12.9f seconds/op)\n", 1/stats[_STAT_DELETE].best,stats[_STAT_DELETE].best); printf(" Worst delete(s)/sec = %12.2f (%12.9f seconds/op)\n\n", 1/stats[_STAT_DELETE].worst,stats[_STAT_DELETE].worst); } if(!verbose) { printf("%c %4d %7.0f ",'A',x,stats[_STAT_DIR_CREATE].counter/stats[_STAT_DIR_CREATE].total_time); printf("%7.0f ",stats[_STAT_DIR_TRAVERSE].counter/stats[_STAT_DIR_TRAVERSE].total_time); printf("%7.0f ",stats[_STAT_DIR_DELETE].counter/stats[_STAT_DIR_DELETE].total_time); printf("%7.0f ",stats[_STAT_CREATE].counter/stats[_STAT_CREATE].total_time); printf("%7.0f ",stats[_STAT_OPEN].counter/stats[_STAT_OPEN].total_time); printf("%7.0f ",stats[_STAT_READ].counter/stats[_STAT_READ].total_time); printf("%7.0f ",stats[_STAT_WRITE].counter/stats[_STAT_WRITE].total_time); printf("%7.0f ",stats[_STAT_CLOSE].counter/stats[_STAT_CLOSE].total_time); printf("%7.0f ",stats[_STAT_STAT].counter/stats[_STAT_STAT].total_time); printf("%7.0f ",stats[_STAT_ACCESS].counter/stats[_STAT_ACCESS].total_time); printf("%7.0f ",stats[_STAT_CHMOD].counter/stats[_STAT_CHMOD].total_time); printf("%7.0f ",stats[_STAT_READDIR].counter/stats[_STAT_READDIR].total_time); #ifndef Windows printf("%7.0f ",stats[_STAT_LINK].counter/stats[_STAT_LINK].total_time); printf("%7.0f ",stats[_STAT_UNLINK].counter/stats[_STAT_UNLINK].total_time); #endif printf("%7.0f ",stats[_STAT_DELETE].counter/stats[_STAT_DELETE].total_time); printf("%10d ",x*x*x); printf("\n"); fflush(stdout); if(best) { printf("%c %4d %7.0f ",'B',x, 1/stats[_STAT_DIR_CREATE].best); printf("%7.0f ",1/stats[_STAT_DIR_TRAVERSE].best); printf("%7.0f ",1/stats[_STAT_DIR_DELETE].best); printf("%7.0f ",1/stats[_STAT_CREATE].best); printf("%7.0f ",1/stats[_STAT_OPEN].best); printf("%7.0f ",1/stats[_STAT_READ].best); printf("%7.0f ",1/stats[_STAT_WRITE].best); printf("%7.0f ",1/stats[_STAT_CLOSE].best); printf("%7.0f ",1/stats[_STAT_STAT].best); printf("%7.0f ",1/stats[_STAT_ACCESS].best); printf("%7.0f ",1/stats[_STAT_CHMOD].best); printf("%7.0f ",1/stats[_STAT_READDIR].best); #ifndef Windows printf("%7.0f ",1/stats[_STAT_LINK].best); printf("%7.0f ",1/stats[_STAT_UNLINK].best); #endif printf("%7.0f ",1/stats[_STAT_DELETE].best); printf("%10d ",x*x*x); printf("\n"); fflush(stdout); } if(worst) { printf("%c %4d %7.0f ",'W',x, 1/stats[_STAT_DIR_CREATE].worst); printf("%7.0f ",1/stats[_STAT_DIR_TRAVERSE].worst); printf("%7.0f ",1/stats[_STAT_DIR_DELETE].worst); printf("%7.0f ",1/stats[_STAT_CREATE].worst); printf("%7.0f ",1/stats[_STAT_OPEN].worst); printf("%7.0f ",1/stats[_STAT_READ].worst); printf("%7.0f ",1/stats[_STAT_WRITE].worst); printf("%7.0f ",1/stats[_STAT_CLOSE].worst); printf("%7.0f ",1/stats[_STAT_STAT].worst); printf("%7.0f ",1/stats[_STAT_ACCESS].worst); printf("%7.0f ",1/stats[_STAT_CHMOD].worst); printf("%7.0f ",1/stats[_STAT_READDIR].worst); #ifndef Windows printf("%7.0f ",1/stats[_STAT_LINK].worst); printf("%7.0f ",1/stats[_STAT_UNLINK].worst); #endif printf("%7.0f ",1/stats[_STAT_DELETE].worst); printf("%10d ",x*x*x); printf("\n"); fflush(stdout); } } } return(0); } void dir_create(int x) { int i,j,k; int ret; char buf[100]; stats[_STAT_DIR_CREATE].best=(double)99999.9; stats[_STAT_DIR_CREATE].worst=(double)0.00000000; for(i=0;i stats[_STAT_DIR_CREATE].worst) stats[_STAT_DIR_CREATE].worst=stats[_STAT_DIR_CREATE].speed; junk=chdir(buf); for(j=0;j stats[_STAT_DIR_CREATE].worst) stats[_STAT_DIR_CREATE].worst=stats[_STAT_DIR_CREATE].speed; junk=chdir(buf); for(k=0;k stats[_STAT_DIR_CREATE].worst) stats[_STAT_DIR_CREATE].worst=stats[_STAT_DIR_CREATE].speed; junk=chdir(buf); junk=chdir(".."); } junk=chdir(".."); } junk=chdir(".."); } } void dir_traverse(int x) { int i,j,k; char buf[100]; double time1, time2; stats[_STAT_DIR_TRAVERSE].best=(double)99999.9; stats[_STAT_DIR_TRAVERSE].worst=(double)0.00000000; for(i=0;i stats[_STAT_DIR_TRAVERSE].worst) stats[_STAT_DIR_TRAVERSE].worst=stats[_STAT_DIR_TRAVERSE].speed; } stats[_STAT_DIR_TRAVERSE].starttime=time_so_far(); junk=chdir(".."); stats[_STAT_DIR_TRAVERSE].endtime=time_so_far(); stats[_STAT_DIR_TRAVERSE].speed=time2+stats[_STAT_DIR_TRAVERSE].endtime-stats[_STAT_DIR_TRAVERSE].starttime; if(stats[_STAT_DIR_TRAVERSE].speed < (double)0.0) stats[_STAT_DIR_TRAVERSE].speed=(double) 0.0; stats[_STAT_DIR_TRAVERSE].total_time+=stats[_STAT_DIR_TRAVERSE].speed; stats[_STAT_DIR_TRAVERSE].counter++; if(stats[_STAT_DIR_TRAVERSE].speed < stats[_STAT_DIR_TRAVERSE].best) stats[_STAT_DIR_TRAVERSE].best=stats[_STAT_DIR_TRAVERSE].speed; if(stats[_STAT_DIR_TRAVERSE].speed > stats[_STAT_DIR_TRAVERSE].worst) stats[_STAT_DIR_TRAVERSE].worst=stats[_STAT_DIR_TRAVERSE].speed; } stats[_STAT_DIR_TRAVERSE].starttime=time_so_far(); junk=chdir(".."); stats[_STAT_DIR_TRAVERSE].endtime=time_so_far(); stats[_STAT_DIR_TRAVERSE].speed=time1+stats[_STAT_DIR_TRAVERSE].endtime-stats[_STAT_DIR_TRAVERSE].starttime; if(stats[_STAT_DIR_TRAVERSE].speed < (double)0.0) stats[_STAT_DIR_TRAVERSE].speed=(double)0.0; stats[_STAT_DIR_TRAVERSE].total_time+=stats[_STAT_DIR_TRAVERSE].speed; stats[_STAT_DIR_TRAVERSE].counter++; if(stats[_STAT_DIR_TRAVERSE].speed < stats[_STAT_DIR_TRAVERSE].best) stats[_STAT_DIR_TRAVERSE].best=stats[_STAT_DIR_TRAVERSE].speed; if(stats[_STAT_DIR_TRAVERSE].speed > stats[_STAT_DIR_TRAVERSE].worst) stats[_STAT_DIR_TRAVERSE].worst=stats[_STAT_DIR_TRAVERSE].speed; } } void file_create(int x) { int i,j,k; int fd; int ret; char buf[100]; char value; stats[_STAT_CREATE].best=(double)999999.9; stats[_STAT_CREATE].worst=(double)0.0; stats[_STAT_WRITE].best=(double)999999.9; stats[_STAT_WRITE].worst=(double)0.0; stats[_STAT_CLOSE].best=(double)999999.9; stats[_STAT_CLOSE].worst=(double)0.0; for(i=0;i stats[_STAT_CREATE].worst) stats[_STAT_CREATE].worst=stats[_STAT_CREATE].speed; stats[_STAT_WRITE].starttime=time_so_far(); junk=write(fd,mbuffer,sz); stats[_STAT_WRITE].endtime=time_so_far(); stats[_STAT_WRITE].counter++; stats[_STAT_WRITE].speed=stats[_STAT_WRITE].endtime-stats[_STAT_WRITE].starttime; if(stats[_STAT_WRITE].speed < (double)0.0) stats[_STAT_WRITE].speed=(double)0.0; stats[_STAT_WRITE].total_time+=stats[_STAT_WRITE].speed; if(stats[_STAT_WRITE].speed < stats[_STAT_WRITE].best) stats[_STAT_WRITE].best=stats[_STAT_WRITE].speed; if(stats[_STAT_WRITE].speed > stats[_STAT_WRITE].worst) stats[_STAT_WRITE].worst=stats[_STAT_WRITE].speed; fsync(fd); stats[_STAT_CLOSE].starttime=time_so_far(); close(fd); stats[_STAT_CLOSE].endtime=time_so_far(); stats[_STAT_CLOSE].speed=stats[_STAT_CLOSE].endtime-stats[_STAT_CLOSE].starttime; if(stats[_STAT_CLOSE].speed < (double)0.0) stats[_STAT_CLOSE].speed=(double)0.0; stats[_STAT_CLOSE].total_time+=stats[_STAT_CLOSE].speed; stats[_STAT_CLOSE].counter++; if(stats[_STAT_CLOSE].speed < stats[_STAT_CLOSE].best) stats[_STAT_CLOSE].best=stats[_STAT_CLOSE].speed; if(stats[_STAT_CLOSE].speed > stats[_STAT_CLOSE].worst) stats[_STAT_CLOSE].worst=stats[_STAT_CLOSE].speed; } junk=chdir(".."); } junk=chdir(".."); } } void file_stat(int x) { int i,j,k,y; char buf[100]; struct stat mystat; stats[_STAT_STAT].best=(double)99999.9; stats[_STAT_STAT].worst=(double)0.00000000; for(i=0;i stats[_STAT_STAT].worst) stats[_STAT_STAT].worst=stats[_STAT_STAT].speed; } junk=chdir(".."); } junk=chdir(".."); } } void file_access(int x) { int i,j,k,y; char buf[100]; stats[_STAT_ACCESS].best=(double)999999.9; stats[_STAT_ACCESS].worst=(double)0.0; for(i=0;i stats[_STAT_ACCESS].worst) stats[_STAT_ACCESS].worst=stats[_STAT_ACCESS].speed; } junk=chdir(".."); } junk=chdir(".."); } } void file_chmod(int x) { int i,j,k,y; char buf[100]; stats[_STAT_CHMOD].best=(double)999999.9; stats[_STAT_CHMOD].worst=(double)0.0; for(i=0;i stats[_STAT_CHMOD].worst) stats[_STAT_CHMOD].worst=stats[_STAT_CHMOD].speed; } junk=chdir(".."); } junk=chdir(".."); } } void file_readdir(int x) { int i,j,ret1; char buf[100]; DIR *dirbuf; struct dirent *y; stats[_STAT_READDIR].best=(double)999999.9; stats[_STAT_READDIR].worst=(double)0.0; for(i=0;i stats[_STAT_READDIR].worst) stats[_STAT_READDIR].worst=stats[_STAT_READDIR].speed; ret1=closedir(dirbuf); if(ret1 < 0) { printf("closedir failed\n"); exit(1); } junk=chdir(".."); } junk=chdir(".."); } } void file_link(int x) { int i,j,k,y; char buf[100]; char bufn[100]; stats[_STAT_LINK].best=(double)999999.9; stats[_STAT_LINK].worst=(double)0.0; for(i=0;i stats[_STAT_LINK].worst) stats[_STAT_LINK].worst=stats[_STAT_LINK].speed; } junk=chdir(".."); } junk=chdir(".."); } } void file_unlink(int x) { int i,j,k,y; char buf[100]; char bufn[100]; stats[_STAT_UNLINK].best=(double)999999.9; stats[_STAT_UNLINK].worst=(double)0.0; for(i=0;i stats[_STAT_UNLINK].worst) stats[_STAT_UNLINK].worst=stats[_STAT_UNLINK].speed; } junk=chdir(".."); } junk=chdir(".."); } } void dir_delete(int x) { int i,j,k; char buf[100]; stats[_STAT_DIR_DELETE].best=(double)99999.9; stats[_STAT_DIR_DELETE].worst=(double)0.00000000; for(i=0;i stats[_STAT_DIR_DELETE].worst) stats[_STAT_DIR_DELETE].worst=stats[_STAT_DIR_DELETE].speed; } junk=chdir(".."); sprintf(buf,"fileop_L1_%d_L2_%d",i,j); stats[_STAT_DIR_DELETE].starttime=time_so_far(); rmdir(buf); stats[_STAT_DIR_DELETE].endtime=time_so_far(); stats[_STAT_DIR_DELETE].speed=stats[_STAT_DIR_DELETE].endtime-stats[_STAT_DIR_DELETE].starttime; if(stats[_STAT_DIR_DELETE].speed < (double)0.0) stats[_STAT_DIR_DELETE].speed=(double)0.0; stats[_STAT_DIR_DELETE].total_time+=stats[_STAT_DIR_DELETE].speed; stats[_STAT_DIR_DELETE].counter++; if(stats[_STAT_DIR_DELETE].speed < stats[_STAT_DIR_DELETE].best) stats[_STAT_DIR_DELETE].best=stats[_STAT_DIR_DELETE].speed; if(stats[_STAT_DIR_DELETE].speed > stats[_STAT_DIR_DELETE].worst) stats[_STAT_DIR_DELETE].worst=stats[_STAT_DIR_DELETE].speed; } junk=chdir(".."); sprintf(buf,"fileop_L1_%d",i); stats[_STAT_DIR_DELETE].starttime=time_so_far(); rmdir(buf); stats[_STAT_DIR_DELETE].endtime=time_so_far(); stats[_STAT_DIR_DELETE].speed=stats[_STAT_DIR_DELETE].endtime-stats[_STAT_DIR_DELETE].starttime; if(stats[_STAT_DIR_DELETE].speed < (double)0.0) stats[_STAT_DIR_DELETE].speed=(double)0.0; stats[_STAT_DIR_DELETE].total_time+=stats[_STAT_DIR_DELETE].speed; stats[_STAT_DIR_DELETE].counter++; if(stats[_STAT_DIR_DELETE].speed < stats[_STAT_DIR_DELETE].best) stats[_STAT_DIR_DELETE].best=stats[_STAT_DIR_DELETE].speed; if(stats[_STAT_DIR_DELETE].speed > stats[_STAT_DIR_DELETE].worst) stats[_STAT_DIR_DELETE].worst=stats[_STAT_DIR_DELETE].speed; } } void file_delete(int x) { int i,j,k; char buf[100]; stats[_STAT_DELETE].best=(double)999999.9; stats[_STAT_DELETE].worst=(double)0.0; for(i=0;i stats[_STAT_DELETE].worst) stats[_STAT_DELETE].worst=stats[_STAT_DELETE].speed; } junk=chdir(".."); sprintf(buf,"fileop_L1_%d_L2_%d",i,j); rmdir(buf); } junk=chdir(".."); sprintf(buf,"fileop_L1_%d",i); rmdir(buf); } } void file_read(int x) { int i,j,k,y,fd; char buf[100]; char value; stats[_STAT_READ].best=(double)99999.9; stats[_STAT_READ].worst=(double)0.00000000; stats[_STAT_OPEN].best=(double)99999.9; stats[_STAT_OPEN].worst=(double)0.00000000; for(i=0;i stats[_STAT_OPEN].worst) stats[_STAT_OPEN].worst=stats[_STAT_OPEN].speed; stats[_STAT_READ].starttime=time_so_far(); y=read(fd,mbuffer,sz); if(y < 0) { printf("Read failed\n"); exit(1); } if(validate(mbuffer,sz, value) !=0) printf("Error: Data Mis-compare\n");; stats[_STAT_READ].endtime=time_so_far(); close(fd); stats[_STAT_READ].speed=stats[_STAT_READ].endtime-stats[_STAT_READ].starttime; if(stats[_STAT_READ].speed < (double)0.0) stats[_STAT_READ].speed=(double)0.0; stats[_STAT_READ].total_time+=stats[_STAT_READ].speed; stats[_STAT_READ].counter++; if(stats[_STAT_READ].speed < stats[_STAT_READ].best) stats[_STAT_READ].best=stats[_STAT_READ].speed; if(stats[_STAT_READ].speed > stats[_STAT_READ].worst) stats[_STAT_READ].worst=stats[_STAT_READ].speed; } junk=chdir(".."); } junk=chdir(".."); } } /************************************************************************/ /* Time measurement routines. Thanks to Iozone :-) */ /************************************************************************/ #ifdef HAVE_ANSIC_C static double time_so_far(void) #else static double time_so_far() #endif { #ifdef Windows LARGE_INTEGER freq,counter; double wintime,bigcounter; /* For Windows the time_of_day() is useless. It increments in 55 milli second */ /* increments. By using the Win32api one can get access to the high performance */ /* measurement interfaces. With this one can get back into the 8 to 9 */ /* microsecond resolution. */ QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&counter); bigcounter=(double)counter.HighPart *(double)0xffffffff + (double)counter.LowPart; wintime = (double)(bigcounter/(double)freq.LowPart); return((double)wintime); #else #if defined (OSFV4) || defined(OSFV3) || defined(OSFV5) struct timespec gp; if (getclock(TIMEOFDAY, (struct timespec *) &gp) == -1) perror("getclock"); return (( (double) (gp.tv_sec)) + ( ((float)(gp.tv_nsec)) * 0.000000001 )); #else struct timeval tp; if (gettimeofday(&tp, (struct timezone *) NULL) == -1) perror("gettimeofday"); return ((double) (tp.tv_sec)) + (((double) tp.tv_usec) * 0.000001 ); #endif #endif } void splash(void) { printf("\n"); printf(" --------------------------------------\n"); printf(" | Fileop | \n"); printf(" | %s | \n",version); printf(" | | \n"); printf(" | by |\n"); printf(" | | \n"); printf(" | Don Capps |\n"); printf(" --------------------------------------\n"); printf("\n"); } void usage(void) { splash(); printf(" fileop [-f X ]|[-l # -u #] [-s Y] [-e] [-b] [-w] [-d ] [-t] [-v] [-h]\n"); printf("\n"); printf(" -f # Force factor. X^3 files will be created and removed.\n"); printf(" -l # Lower limit on the value of the Force factor.\n"); printf(" -u # Upper limit on the value of the Force factor.\n"); printf(" -s # Optional. Sets filesize for the create/write. May use suffix 'K' or 'M'.\n"); printf(" -e Excel importable format.\n"); printf(" -b Output best case results.\n"); printf(" -i # Increment force factor by this increment.\n"); printf(" -w Output worst case results.\n"); printf(" -d Specify starting directory.\n"); printf(" -U Mount point to remount between tests.\n"); printf(" -t Verbose output option.\n"); printf(" -v Version information.\n"); printf(" -h Help text.\n"); printf("\n"); printf(" The structure of the file tree is:\n"); printf(" X number of Level 1 directories, with X number of\n"); printf(" level 2 directories, with X number of files in each\n"); printf(" of the level 2 directories.\n"); printf("\n"); printf(" Example: fileop 2\n"); printf("\n"); printf(" dir_1 dir_2\n"); printf(" / \\ / \\ \n"); printf(" sdir_1 sdir_2 sdir_1 sdir_2\n"); printf(" / \\ / \\ / \\ / \\ \n"); printf(" file_1 file_2 file_1 file_2 file_1 file_2 file_1 file_2\n"); printf("\n"); printf(" Each file will be created, and then Y bytes is written to the file.\n"); printf("\n"); } void clear_stats() { int i; for(i=0;i<_NUM_STATS;i++) memset((char *)&stats[i],0,sizeof(struct stat_struct)); } int validate(char *buffer, int size, char value) { register int i; register char *cp; register char v1; v1=value; cp = buffer; for(i=0;i /* errno declaration & error codes. */ #include /* getaddrinfo(3) et al. */ #include /* sockaddr_in & sockaddr_in6 definition. */ #include /* printf(3) et al. */ #include /* exit(2). */ #include /* String manipulation & memory functions. */ #if defined(_SUA_) #include /* poll(2) and related definitions. */ #else #include /* poll(2) and related definitions. */ #endif #include /* Socket functions (socket(2), bind(2), etc). */ #include /* time(2) & ctime(3). */ #include /* gettimeofday */ #include /* getopt(3), read(2), etc. */ /* Include for Cygnus development environment for Windows */ #if defined (Windows) #include int errno; #endif #if defined(_SUA_) extern char *optarg, *opterr; #endif /* ** Constants. ** ** Please remember to add PIT service to the /etc/services file. */ #define DFLT_SERVICE "PIT" /* Programmable Interdimensional Timer */ #define INVALID_DESC -1 /* Invalid file descriptor. */ #define MAXCONNQLEN 3 /* Max nbr of connection requests to queue. */ #define MAXTCPSCKTS 2 /* One TCP socket for IPv4 & one for IPv6. */ #define MAXUDPSCKTS 2 /* One UDP socket for IPv4 & one for IPv6. */ #define VALIDOPTS "vh:p:" /* Valid command options. */ /* ** Simple boolean type definition. */ int false = 0; int true = 1; /* ** Prototypes for internal helper functions. */ static int openSckt( const char *service, const char *protocol, int desc[ ], size_t *descSize ); static void pit( int tSckt[ ], size_t tScktSize, int uSckt[ ], size_t uScktSize ); /* ** Global data objects. */ static char hostBfr[ NI_MAXHOST ]; /* For use w/getnameinfo(3). */ static const char *pgmName; /* Program name w/o dir prefix. */ static char servBfr[ NI_MAXSERV ]; /* For use w/getnameinfo(3). */ static int verbose = 0; /* Verbose mode indication. */ struct timeval tm; /* Timeval structure, used with gettimeofday() */ char timeStr[40]; /* String for time in microseconds */ char service_name[20]; int need; /* ** Usage macro for command syntax violations. */ #define USAGE \ { \ fprintf( stderr, \ "Usage: %s [-v] -p service \n", \ pgmName ); \ exit( 127 ); \ } /* End USAGE macro. */ /* ** Macro to terminate the program if a system call error occurs. The system ** call must be one of the usual type that returns -1 on error. */ #define CHK(expr) \ do \ { \ if ( (expr) == -1 ) \ { \ fprintf( stderr, \ "%s (line %d): System call ERROR - %s.\n", \ pgmName, \ __LINE__, \ strerror( errno ) ); \ exit( 1 ); \ } /* End IF system call failed. */ \ } while ( false ) /****************************************************************************** * Function: main * * Description: * Set up a PIT server and handle network requests. This server * handles both TCP and UDP requests. * * Parameters: * The usual argc and argv parameters to a main() function. * * Return Value: * This is a daemon program and never returns. However, in the degenerate * case where no sockets are created, the function returns zero. ******************************************************************************/ int main( int argc, char *argv[ ] ) { int opt; int tSckt[ MAXTCPSCKTS ]; /* Array of TCP socket descriptors. */ size_t tScktSize = MAXTCPSCKTS; /* Size of uSckt (# of elements). */ int uSckt[ MAXUDPSCKTS ]; /* Array of UDP socket descriptors. */ size_t uScktSize = MAXUDPSCKTS; /* Size of uSckt (# of elements). */ strcpy(service_name,DFLT_SERVICE); /* ** Set the program name (w/o directory prefix). */ pgmName = strrchr( argv[ 0 ], '/' ); pgmName = pgmName == NULL ? argv[ 0 ] : pgmName + 1; /* ** Process command options. */ opterr = 0; /* Turns off "invalid option" error messages. */ while ( ( opt = getopt( argc, argv, VALIDOPTS ) ) >= 0 ) { switch ( opt ) { case 'v': /* Verbose mode. */ { verbose = true; break; } case 'p': /* Get the port number */ { strcpy(service_name,optarg); need++; break; } default: { USAGE; } } /* End SWITCH on command option. */ } /* End WHILE processing options. */ if(need < 1) { USAGE; } /* ** Open both a TCP and UDP socket, for both IPv4 & IPv6, on which to receive ** service requests. */ if ( ( openSckt( service_name, "tcp", tSckt, &tScktSize ) < 0 ) || ( openSckt( service_name, "udp", uSckt, &uScktSize ) < 0 ) ) { exit( 1 ); } /* ** Run the Programmable Interdimensional Timer server. */ if ( ( tScktSize > 0 ) || ( uScktSize > 0 ) ) { pit( tSckt, /* pit() never returns. */ tScktSize, uSckt, uScktSize ); } /* ** Since pit() never returns, execution only gets here if no sockets were ** created. */ if ( verbose ) { fprintf( stderr, "%s: No sockets opened... terminating.\n", pgmName ); } return 0; } /* End main() */ /****************************************************************************** * Function: openSckt * * Description: * Open passive (server) sockets for the indicated inet service & protocol. * Notice in the last sentence that "sockets" is plural. During the interim * transition period while everyone is switching over to IPv6, the server * application has to open two sockets on which to listen for connections... * one for IPv4 traffic and one for IPv6 traffic. * * Parameters: * service - Pointer to a character string representing the well-known port * on which to listen (can be a service name or a decimal number). * protocol - Pointer to a character string representing the transport layer * protocol (only "tcp" or "udp" are valid). * desc - Pointer to an array into which the socket descriptors are * placed when opened. * descSize - This is a value-result parameter. On input, it contains the * max number of descriptors that can be put into 'desc' (i.e. the * number of elements in the array). Upon return, it will contain * the number of descriptors actually opened. Any unused slots in * 'desc' are set to INVALID_DESC. * * Return Value: * 0 on success, -1 on error. ******************************************************************************/ static int openSckt( const char *service, const char *protocol, int desc[ ], size_t *descSize ) { struct addrinfo *ai; int aiErr; struct addrinfo *aiHead; struct addrinfo hints = { .ai_flags = AI_PASSIVE, /* Server mode. */ .ai_family = PF_UNSPEC }; /* IPv4 or IPv6. */ size_t maxDescs = *descSize; /* ** Initialize output parameters. When the loop completes, *descSize is 0. */ while ( *descSize > 0 ) { desc[ --( *descSize ) ] = INVALID_DESC; } /* ** Check which protocol is selected (only TCP and UDP are valid). */ if ( strcmp( protocol, "tcp" ) == 0 ) /* TCP protocol. */ { hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; } else if ( strcmp( protocol, "udp" ) == 0 ) /* UDP protocol. */ { hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; } else /* Invalid protocol. */ { fprintf( stderr, "%s (line %d): ERROR - Unknown transport " "layer protocol \"%s\".\n", pgmName, __LINE__, protocol ); return -1; } /* ** Look up the service's "well-known" port number. Notice that NULL is being ** passed for the 'node' parameter, and that the AI_PASSIVE flag is set in ** 'hints'. Thus, the program is requesting passive address information. ** The network address is initialized to :: (all zeros) for IPv6 records, or ** 0.0.0.0 for IPv4 records. */ if ( ( aiErr = getaddrinfo( NULL, service, &hints, &aiHead ) ) != 0 ) { fprintf( stderr, "%s (line %d): ERROR - %s.\n", pgmName, __LINE__, gai_strerror( aiErr ) ); return -1; } /* ** For each of the address records returned, attempt to set up a passive ** socket. */ for ( ai = aiHead; ( ai != NULL ) && ( *descSize < maxDescs ); ai = ai->ai_next ) { if ( verbose ) { /* ** Display the current address info. Start with the protocol- ** independent fields first. */ fprintf( stderr, "Setting up a passive socket based on the " "following address info:\n" " ai_flags = 0x%02X\n" " ai_family = %d (PF_INET = %d, PF_INET6 = %d)\n" " ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d)\n" " ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d)\n" " ai_addrlen = %d (sockaddr_in = %zu, " "sockaddr_in6 = %zu)\n", ai->ai_flags, ai->ai_family, PF_INET, PF_INET6, ai->ai_socktype, SOCK_STREAM, SOCK_DGRAM, ai->ai_protocol, IPPROTO_TCP, IPPROTO_UDP, ai->ai_addrlen, sizeof( struct sockaddr_in ), sizeof( struct sockaddr_in6 ) ); /* ** Now display the protocol-specific formatted socket address. Note ** that the program is requesting that getnameinfo(3) convert the ** host & service into numeric strings. */ getnameinfo( ai->ai_addr, ai->ai_addrlen, hostBfr, sizeof( hostBfr ), servBfr, sizeof( servBfr ), NI_NUMERICHOST | NI_NUMERICSERV ); switch ( ai->ai_family ) { case PF_INET: /* IPv4 address record. */ { struct sockaddr_in *p = (struct sockaddr_in*) ai->ai_addr; fprintf( stderr, " ai_addr = sin_family: %d (AF_INET = %d, " "AF_INET6 = %d)\n" " sin_addr: %s\n" " sin_port: %s\n", p->sin_family, AF_INET, AF_INET6, hostBfr, servBfr ); break; } /* End CASE of IPv4. */ case PF_INET6: /* IPv6 address record. */ { struct sockaddr_in6 *p = (struct sockaddr_in6*) ai->ai_addr; fprintf( stderr, " ai_addr = sin6_family: %d (AF_INET = %d, " "AF_INET6 = %d)\n" " sin6_addr: %s\n" " sin6_port: %s\n" " sin6_flowinfo: %d\n" " sin6_scope_id: %d\n", p->sin6_family, AF_INET, AF_INET6, hostBfr, servBfr, p->sin6_flowinfo, p->sin6_scope_id ); break; } /* End CASE of IPv6. */ default: /* Can never get here, but just for completeness. */ { fprintf( stderr, "%s (line %d): ERROR - Unknown protocol family (%d).\n", pgmName, __LINE__, ai->ai_family ); freeaddrinfo( aiHead ); return -1; } /* End DEFAULT case (unknown protocol family). */ } /* End SWITCH on protocol family. */ } /* End IF verbose mode. */ /* ** Create a socket using the info in the addrinfo structure. */ CHK( desc[ *descSize ] = socket( ai->ai_family, ai->ai_socktype, ai->ai_protocol ) ); /* ** Here is the code that prevents "IPv4 mapped addresses", as discussed ** in Section 22.1.3.1. If an IPv6 socket was just created, then set the ** IPV6_V6ONLY socket option. */ if ( ai->ai_family == PF_INET6 ) { #if defined( IPV6_V6ONLY ) /* ** Disable IPv4 mapped addresses. */ int v6Only = 1; CHK( setsockopt( desc[ *descSize ], IPPROTO_IPV6, IPV6_V6ONLY, &v6Only, sizeof( v6Only ) ) ); #else /* ** IPV6_V6ONLY is not defined, so the socket option can't be set and ** thus IPv4 mapped addresses can't be disabled. Print a warning ** message and close the socket. Design note: If the ** #if...#else...#endif construct were removed, then this program ** would not compile (because IPV6_V6ONLY isn't defined). That's an ** acceptable approach; IPv4 mapped addresses are certainly disabled ** if the program can't build! However, since this program is also ** designed to work for IPv4 sockets as well as IPv6, I decided to ** allow the program to compile when IPV6_V6ONLY is not defined, and ** turn it into a run-time warning rather than a compile-time error. ** IPv4 mapped addresses are still disabled because _all_ IPv6 traffic ** is disabled (all IPv6 sockets are closed here), but at least this ** way the server can still service IPv4 network traffic. */ fprintf( stderr, "%s (line %d): WARNING - Cannot set IPV6_V6ONLY socket " "option. Closing IPv6 %s socket.\n", pgmName, __LINE__, ai->ai_protocol == IPPROTO_TCP ? "TCP" : "UDP" ); CHK( close( desc[ *descSize ] ) ); continue; /* Go to top of FOR loop w/o updating *descSize! */ #endif /* IPV6_V6ONLY */ } /* End IF this is an IPv6 socket. */ /* ** Bind the socket. Again, the info from the addrinfo structure is used. */ CHK( bind( desc[ *descSize ], ai->ai_addr, ai->ai_addrlen ) ); /* ** If this is a TCP socket, put the socket into passive listening mode ** (listen is only valid on connection-oriented sockets). */ if ( ai->ai_socktype == SOCK_STREAM ) { CHK( listen( desc[ *descSize ], MAXCONNQLEN ) ); } /* ** Socket set up okay. Bump index to next descriptor array element. */ *descSize += 1; } /* End FOR each address info structure returned. */ /* ** Dummy check for unused address records. */ if ( verbose && ( ai != NULL ) ) { fprintf( stderr, "%s (line %d): WARNING - Some address records were " "not processed due to insufficient array space.\n", pgmName, __LINE__ ); } /* End IF verbose and some address records remain unprocessed. */ /* ** Clean up. */ freeaddrinfo( aiHead ); return 0; } /* End openSckt() */ /****************************************************************************** * Function: pit * * Description: * Listen on a set of sockets and send the current microsecond counter * that was produced by gettimeofday(), to any clients. This function * never returns. * * Parameters: * tSckt - Array of TCP socket descriptors on which to listen. * tScktSize - Size of the tSckt array (nbr of elements). * uSckt - Array of UDP socket descriptors on which to listen. * uScktSize - Size of the uSckt array (nbr of elements). * * Return Value: None. ******************************************************************************/ static void pit( int tSckt[ ], size_t tScktSize, int uSckt[ ], size_t uScktSize ) { char bfr[ 256 ]; ssize_t count; struct pollfd *desc; size_t descSize = tScktSize + uScktSize; int idx; int newSckt; struct sockaddr *sadr; socklen_t sadrLen; struct sockaddr_storage sockStor; int status; size_t timeLen; time_t timeVal; ssize_t wBytes; unsigned long long secs; int ret; /* ** Allocate memory for the poll(2) array. */ desc = malloc( descSize * sizeof( struct pollfd ) ); if ( desc == NULL ) { fprintf( stderr, "%s (line %d): ERROR - %s.\n", pgmName, __LINE__, strerror( ENOMEM ) ); exit( 1 ); } /* ** Initialize the poll(2) array. */ for ( idx = 0; idx < descSize; idx++ ) { desc[ idx ].fd = idx < tScktSize ? tSckt[ idx ] : uSckt[ idx - tScktSize ]; desc[ idx ].events = POLLIN; desc[ idx ].revents = 0; } /* ** Main PIT server loop. Handles both TCP & UDP requests. This is ** an interative server, and all requests are handled directly within the ** main loop. */ while ( true ) /* Do forever. */ { /* ** Wait for activity on one of the sockets. The DO..WHILE construct is ** used to restart the system call in the event the process is ** interrupted by a signal. */ do { status = poll( desc, descSize, -1 /* Wait indefinitely for input. */ ); } while ( ( status < 0 ) && ( errno == EINTR ) ); CHK( status ); /* Check for a bona fide system call error. */ /* ** Get the current time. */ #if defined(Windows) LARGE_INTEGER freq,counter; double wintime,bigcounter; /* For Windows the time_of_day() is useless. It increments in 55 milli * second increments. By using the Win32api one can get access to the * high performance measurement interfaces. With this one can get back * into the 8 to 9 microsecond resolution. */ QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&counter); bigcounter=(double)counter.HighPart *(double)0xffffffff + (double)counter.LowPart; wintime = (double)(bigcounter/(double)freq.LowPart); secs = (long long)(wintime * 1000000); #else ret = gettimeofday( &tm,0 ); secs = ((unsigned long long)tm.tv_sec * 1000000) + (unsigned long long)tm.tv_usec; #endif ret = sprintf(timeStr,"%llu",secs); timeLen = strlen( timeStr ); /* ** Process sockets with input available. */ for ( idx = 0; idx < descSize; idx++ ) { switch ( desc[ idx ].revents ) { case 0: /* No activity on this socket; try the next. */ continue; case POLLIN: /* Network activity. Go process it. */ break; default: /* Invalid poll events. */ { fprintf( stderr, "%s (line %d): ERROR - Invalid poll event (0x%02X).\n", pgmName, __LINE__, desc[ idx ].revents ); exit( 1 ); } } /* End SWITCH on returned poll events. */ /* ** Determine if this is a TCP request or UDP request. */ if ( idx < tScktSize ) { /* ** TCP connection requested. Accept it. Notice the use of ** the sockaddr_storage data type. */ sadrLen = sizeof( sockStor ); sadr = (struct sockaddr*) &sockStor; CHK( newSckt = accept( desc[ idx ].fd, sadr, &sadrLen ) ); CHK( shutdown( newSckt, /* Server never recv's anything. */ SHUT_RD ) ); if ( verbose ) { /* ** Display the socket address of the remote client. Begin with ** the address-independent fields. */ fprintf( stderr, "Sockaddr info for new TCP client:\n" " sa_family = %d (AF_INET = %d, AF_INET6 = %d)\n" " addr len = %d (sockaddr_in = %zu, " "sockaddr_in6 = %zu)\n", sadr->sa_family, AF_INET, AF_INET6, sadrLen, sizeof( struct sockaddr_in ), sizeof( struct sockaddr_in6 ) ); /* ** Display the address-specific fields. */ getnameinfo( sadr, sadrLen, hostBfr, sizeof( hostBfr ), servBfr, sizeof( servBfr ), NI_NUMERICHOST | NI_NUMERICSERV ); /* ** Notice that we're switching on an address family now, not a ** protocol family. */ switch ( sadr->sa_family ) { case AF_INET: /* IPv4 address. */ { struct sockaddr_in *p = (struct sockaddr_in*) sadr; fprintf( stderr, " sin_addr = sin_family: %d\n" " sin_addr: %s\n" " sin_port: %s\n", p->sin_family, hostBfr, servBfr ); break; } /* End CASE of IPv4. */ case AF_INET6: /* IPv6 address. */ { struct sockaddr_in6 *p = (struct sockaddr_in6*) sadr; fprintf( stderr, " sin6_addr = sin6_family: %d\n" " sin6_addr: %s\n" " sin6_port: %s\n" " sin6_flowinfo: %d\n" " sin6_scope_id: %d\n", p->sin6_family, hostBfr, servBfr, p->sin6_flowinfo, p->sin6_scope_id ); break; } /* End CASE of IPv6. */ default: /* Can never get here, but for completeness. */ { fprintf( stderr, "%s (line %d): ERROR - Unknown address " "family (%d).\n", pgmName, __LINE__, sadr->sa_family ); break; } /* End DEFAULT case (unknown address family). */ } /* End SWITCH on address family. */ } /* End IF verbose mode. */ /* ** Send the PIT to the client. */ wBytes = timeLen; while ( wBytes > 0 ) { do { count = write( newSckt, timeStr, wBytes ); } while ( ( count < 0 ) && ( errno == EINTR ) ); CHK( count ); /* Check for an error. */ wBytes -= count; } /* End WHILE there is data to send. */ CHK( close( newSckt ) ); } /* End IF this was a TCP connection request. */ else { /* ** This is a UDP socket, and a datagram is available. The funny ** thing about UDP requests is that this server doesn't require any ** client input; but it can't send the PIT unless it knows a client ** wants the data, and the only way that can occur with UDP is if ** the server receives a datagram from the client. Thus, the ** server must receive _something_, but the content of the datagram ** is irrelevant. Read in the datagram. Again note the use of ** sockaddr_storage to receive the address. */ sadrLen = sizeof( sockStor ); sadr = (struct sockaddr*) &sockStor; CHK( count = recvfrom( desc[ idx ].fd, bfr, sizeof( bfr ), 0, sadr, &sadrLen ) ); /* ** Display whatever was received on stdout. */ if ( verbose ) { ssize_t rBytes = count; fprintf( stderr, "%s: UDP datagram received (%zd bytes).\n", pgmName, count ); while ( count > 0 ) { fputc( bfr[ rBytes - count-- ], stdout ); } if ( bfr[ rBytes-1 ] != '\n' ) fputc( '\n', stdout ); /* Newline also flushes stdout. */ /* ** Display the socket address of the remote client. Address- ** independent fields first. */ fprintf( stderr, "Remote client's sockaddr info:\n" " sa_family = %d (AF_INET = %d, AF_INET6 = %d)\n" " addr len = %d (sockaddr_in = %zu, " "sockaddr_in6 = %zu)\n", sadr->sa_family, AF_INET, AF_INET6, sadrLen, sizeof( struct sockaddr_in ), sizeof( struct sockaddr_in6 ) ); /* ** Display the address-specific information. */ getnameinfo( sadr, sadrLen, hostBfr, sizeof( hostBfr ), servBfr, sizeof( servBfr ), NI_NUMERICHOST | NI_NUMERICSERV ); switch ( sadr->sa_family ) { case AF_INET: /* IPv4 address. */ { struct sockaddr_in *p = (struct sockaddr_in*) sadr; fprintf( stderr, " sin_addr = sin_family: %d\n" " sin_addr: %s\n" " sin_port: %s\n", p->sin_family, hostBfr, servBfr ); break; } /* End CASE of IPv4 address. */ case AF_INET6: /* IPv6 address. */ { struct sockaddr_in6 *p = (struct sockaddr_in6*) sadr; fprintf( stderr, " sin6_addr = sin6_family: %d\n" " sin6_addr: %s\n" " sin6_port: %s\n" " sin6_flowinfo: %d\n" " sin6_scope_id: %d\n", p->sin6_family, hostBfr, servBfr, p->sin6_flowinfo, p->sin6_scope_id ); break; } /* End CASE of IPv6 address. */ default: /* Can never get here, but for completeness. */ { fprintf( stderr, "%s (line %d): ERROR - Unknown address " "family (%d).\n", pgmName, __LINE__, sadr->sa_family ); break; } /* End DEFAULT case (unknown address family). */ } /* End SWITCH on address family. */ } /* End IF verbose mode. */ /* ** Send the PIT to the client. */ wBytes = timeLen; while ( wBytes > 0 ) { do { count = sendto( desc[ idx ].fd, timeStr, wBytes, 0, sadr, /* Address & address length */ sadrLen ); /* received in recvfrom(). */ } while ( ( count < 0 ) && ( errno == EINTR ) ); CHK( count ); /* Check for a bona fide error. */ wBytes -= count; } /* End WHILE there is data to send. */ } /* End ELSE a UDP datagram is available. */ desc[ idx ].revents = 0; /* Clear the returned poll events. */ } /* End FOR each socket descriptor. */ } /* End WHILE forever. */ } /* End pit() */ iozone3_488/docs/iozone.10000444000175000017500000004207213573734166014404 0ustar cappscapps.TH IOZONE 1 .SH NAME Iozone \- Filesystem Benchmark .SH SYNOPSIS .B Iozone .nh [\fB\-a|\-A\fP] [\fB\-s\fP \fIfilesize_Kb\fP] [\fB\-r\fP \fIrecord_size_Kb\fP] [\fB\-f\fP \fI[path]filename\fP] [\fB\-i\fP \fItest\fP] [\fB\-E\fP] [\fB\-p\fP] [\fB\-m\fP] [\fB\-M\fP] [\fB\-t\fP \fIchildren\fP] [\fB\-h\fP] [\fB\-o\fP] [\fB\-l\fP \fImin_number_procs\fP] [\fB\-u\fP \fImax_number_procs\fP] [\fB\-v\fP] [\fB\-R\fP] [\fB\-x\fP] [\fB\-d\fP \fImicroseconds\fP] [\fB\-F\fP \fIpath1 path2...\fP] [\fB\-V\fP \fIpattern \fP] [\fB\-j\fP \fIstride\fP] [\fB\-T\fP] [\fB\-C\fP] [\fB\-B\fP] [\fB\-D\fP] [\fB\-G\fP] [\fB\-I\fP] [\fB\-H\fP \fIdepth\fP] [\fB\-k\fP \fIdepth\fP] [\fB\-U\fP \fImount_point\fP] [\fB\-S\fP \fIcache_size\fP] [\fB\-O\fP] [\fB\-L\fP \fIline_size\fP] [\fB\-K\fP] [\fB\-N\fP] [\fB\-Q\fP] [\fB\-P\fP \fIstart_cpu\fP] [\fB\-c\fP] [\fB\-e\fP] [\fB\-b\fP \fIExcel.xls\fP] [\fB\-J\fP \fImilliseconds\fP] [\fB\-X\fP \fI[path]filename\fP] [\fB\-Y\fP \fI[path]filename\fP] [\fB\-w\fP] [\fB\-W\fP] [\fB\-z\fP] [\fB\-Z\fP] [\fB\-n\fP \fImin_filesize_Kb\fP] [\fB\-g\fP \fImax_filesize_Kb\fP] [\fB\-y\fP \fImin_recordsize_Kb\fP] [\fB\-q\fP \fImax_recordsize_Kb\fP] [\fB\-+d\fP] [\fB\-+u\fP] [\fB\-+m\fP \fIclient_filename\fP] [\fB\-+n\fP] [\fB\-+N\fP] [\fB\-+p\fP \fIpercent_read\fP] [\fB\-+r\fP] [\fB\-+t\fP] [\fB\-+l\fP] [\fB\-+L\fP] [\fB\-+D\fP] [\fB\-+A\fP \fImadvise_selector\fP] [\fB\-+h\fP \fIhostname\fP] [\fB\-+T\fP] [\fB\-+w\fP \fIPercent de-dupable.\fP] .hy .SH DESCRIPTION .B Iozone is a filesystem benchmark tool. The benchmark generates and measures a variety of file operations. .B Iozone has been ported to many machines and runs under many operating systems. This document will cover the many different types of operations that are tested as well as coverage of all of the command line options. .PP .B Iozone is useful for determining a broad filesystem analysis of a vendor's computer platform. The benchmark tests file I/O performance for the following operations. .PP Read, write, re-read, re-write, read backwards, read strided, fread, fwrite, random read/write, pread/pwrite variants .PP While computers are typically purchased with an application in mind it is also likely that over time the application mix will change. Many vendors have enhanced their operating systems to perform well for some frequently used applications. Although this accelerates the I/O for those few applications it is also likely that the system may not perform well for other applications that were not targeted by the operating system. An example of this type of enhancement is: Database. Many operating systems have tested and tuned the filesystem so it works well with databases. While the database users are happy, the other users may not be so happy as the entire system may be giving all of the system resources to the database users at the expense of all other users. As time rolls on the system administrator may decide that a few more office automation tasks could be shifted to this machine. The load may now shift from a random reader application (database) to a sequential reader. The users may discover that the machine is very slow when running this new application and become dissatisfied with the decision to purchase this platform. By using .B Iozone to get a broad filesystem performance coverage the buyer is much more likely to see any hot or cold spots and pick a platform and operating system that is more well balanced. .SH OPTIONS .TP .BI \-a Used to select full automatic mode. Produces output that covers all tested file operations for record sizes of 4k to 16M for file sizes of 64k to 512M. .TP .BI \-A This version of automatic mode provides more coverage but consumes a bunch of time. The .BI \-a option will automatically stop using transfer sizes less than 64k once the file size is 32M or larger. This saves time. The .BI \-A option tells .B Iozone that you are willing to wait and want dense coverage for small transfers even when the file size is very large. .BI NOTE: This option is deprecated in .BI Iozone version 3.61. Use .BI \-az\ \-i\ 0\ \-i\ 1 instead. .TP .BI \-b\ filename Used to specify a filename that will be used for output of an Excel compatible file that contains the results. .TP .BI \-B Use mmap() files. This causes all of the temporary files being measured to be created and accessed with the mmap() interface. Some applications prefer to treat files as arrays of memory. These applications mmap() the file and then just access the array with loads and stores to perform file I/O. .TP .BI \-c Include close() in the timing calculations. This is useful only if you suspect that close() is broken in the operating system currently under test. It can be useful for NFS Version 3 testing as well to help identify if the nfs3_commit is working well. .TP .BI \-C Show bytes transferred by each child in throughput testing. Useful if your operating system has any starvation problems in file I/O or in process management. .TP .BI \-d\ # Microsecond delay out of barrier. During the throughput tests all threads or processes are forced to a barrier before beginning the test. Normally, all of the threads or processes are released at the same moment. This option allows one to delay a specified time in microseconds between releasing each of the processes or threads. .TP .BI \-D Use msync(MS_ASYNC) on mmap files. This tells the operating system that all the data in the mmap space needs to be written to disk asynchronously. .TP .BI \-e Include flush (fsync,fflush) in the timing calculations .TP .BI \-E Used to select the extension tests. Only available on some platforms. Uses pread interfaces. .TP .BI \-f\ filename Used to specify the filename for the temporary file under test. This is useful when the unmount option is used. When testing with unmount between tests it is necessary for the temporary file under test to be in a directory that can be unmounted. It is not possible to unmount the current working directory as the process .B Iozone is running in this directory. .TP .BI \-F\ filename\ filename\ filename\ ? Specify each of the temporary file names to be used in the throughput testing. The number of names should be equal to the number of processes or threads that are specified. .TP .BI \-g\ # Set maximum file size (in Kbytes) for auto mode. One may also specify .BI \-g\ #k (size in Kbytes) or .BI \-g\ #m (size in Mbytes) or .BI \-g\ #g (size in Gbytes). See .BI \-n for minimum file size. .TP .BI \-G Use msync(MS_SYNC) on mmap files. This tells the operating system that all the data in the mmap space needs to be written to disk synchronously. .TP .BI \-h Displays help screen. .TP .BI \-H\ # Use POSIX async I/O with\ # async operations. .B Iozone will use POSIX async I/O with a bcopy from the async buffers back into the applications buffer. Some versions of MSC NASTRAN perform I/O this way. This technique is used by applications so that the async I/O may be performed in a library and requires no changes to the applications internal model. .TP .BI \-i\ # Used to specify which tests to run. (0=write/rewrite, 1=read/re-read, 2=random-read/write, 3=Read-backwards, 4=Re-write-record, 5=stride-read, 6=fwrite/re-fwrite, 7=fread/Re-fread, 8=mixed workload, 9=pwrite/Re-pwrite, 10=pread/Re-pread, 11=pwritev/Re-pwritev, 12=preadv/Re-preadv). One will always need to specify 0 so that any of the following tests will have a file to measure. .BI -i\ #\ -i\ #\ -i\ # is also supported so that one may select more than one test. .TP .BI \-I Use DIRECT IO if possible for all file operations. Tells the filesystem that all operations to the file are to bypass the buffer cache and go directly to disk. (not available on all platforms) .TP .BI \-j\ # Set stride of file accesses to (# * record size). The stride read test will read records at this stride. .TP .BI \-J\ # Millisecond delay before each I/O operation. This simulates the cpu compute cycle of an application that precedes an I/O operation. One may also use .BI \-X or .BI \-Y to control the compute cycle on a per I/O operation basis. .TP .BI \-k\ # Use POSIX async I/O (no bcopy) with\ # async operations. .B Iozone will use POSIX async I/O and will not perform any extra bcopys. The buffers used by .B Iozone will be handed to the async I/O system call directly. .TP .BI \-K Inject some random accesses in the testing. .TP .BI \-l\ # Set the lower limit on number of processes to run. When running throughput tests this option allows the user to specify the least number of processes or threads to start. This option should be used in conjunction with the .BI \-u option. .TP .BI \-L\ # Set processor cache line size to value (in bytes). Tells .B Iozone the processor cache line size. This is used internally to help speed up the test. .TP .BI \-m Tells .B Iozone to use multiple buffers internally. Some applications read into a single buffer over and over. Others have an array of buffers. This option allows both types of applications to be simulated. .B Iozone\'s default behavior is to re-use internal buffers. This option allows one to override the default and to use multiple internal buffers. .TP .BI \-M \.B Iozone will call uname() and will put the string in the output file. .TP .BI \-n\ # Set minimum file size (in Kbytes) for auto mode. One may also specify .BI \-n\ #k (size in Kbytes) or .BI \-n\ #m (size in Mbytes) or .BI \-n\ #g (size in Gbytes). See .BI \-g for maximum file size. .TP .BI \-N Report results in microseconds per operation. .TP .BI \-o Writes are synchronously written to disk. (O_SYNC). .B Iozone will open the files with the O_SYNC flag. This forces all writes to the file to go completely to disk before returning to the benchmark. .TP .BI \-O Give results in operations per second. .TP .BI \-p This purges the processor cache before each file operation. .B Iozone will allocate another internal buffer that is aligned to the same processor cache boundary and is of a size that matches the processor cache. It will zero fill this alternate buffer before beginning each test. This will purge the processor cache and allow one to see the memory subsystem without the acceleration due to the processor cache. .TP .BI \-P\ # Bind processes/threads to processors, starting with this cpu\ #. Only available on some platforms. The first sub process or thread will begin on the specified processor. Future processes or threads will be placed on the next processor. Once the total number of cpus is exceeded then future processes or threads will be placed in a round robin fashion. .TP .BI \-q\ # Set maximum record size (in Kbytes) for auto mode. One may also specify .BI \-q\ #k (size in Kbytes) or .BI \-q\ #m (size in Mbytes) or .BI \-q\ #g (size in Gbytes). See .BI \-y for minimum record size. .TP .BI \-Q Create offset/latency files. .B Iozone will create latency versus offset data files that can be imported with a graphics package and plotted. This is useful for finding if certain offsets have very high latencies. Such as the point where UFS will allocate its first indirect block. One can see from the data the impacts of the extent allocations for extent based filesystems with this option. .TP .BI \-r\ # Used to specify the record size, in Kbytes, to test. One may also specify .BI \-r\ #k (size in Kbytes) or .BI \-r\ #m (size in Mbytes) or .BI \-r\ #g (size in Gbytes). .TP .BI \-R Generate Excel report. .B Iozone will generate an Excel compatible report to standard out. This file may be imported with Microsoft Excel (space delimited) and used to create a graph of the filesystem performance. Note: The 3D graphs are column oriented. You will need to select this when graphing as the default in Excel is row oriented data. .TP .BI \-s\ # Used to specify the size, in Kbytes, of the file to test. One may also specify .BI \-s\ #k (size in Kbytes) or .BI \-s\ #m (size in Mbytes) or .BI \-s\ #g (size in Gbytes). .TP .BI \-S\ # Set processor cache size to value (in Kbytes). This tells .B Iozone the size of the processor cache. It is used internally for buffer alignment and for the purge functionality. .TP .BI \-t\ # Run .B Iozone in a throughput mode. This option allows the user to specify how many threads or processes to have active during the measurement. .TP .BI \-T Use POSIX pthreads for throughput tests. Available on platforms that have POSIX threads. .TP .BI \-u\ # Set the upper limit on number of processes to run. When running throughput tests this option allows the user to specify the greatest number of processes or threads to start. This option should be used in conjunction with the .BI \-l option. .TP .BI \-U\ mountpoint Mount point to unmount and remount between tests. .B Iozone will unmount and remount this mount point before beginning each test. This guarantees that the buffer cache does not contain any of the file under test. .TP .BI \-v Display the version of .B Iozone. .TP .BI \-V\ # Specify a pattern that is to be written to the temporary file and validated for accuracy in each of the read tests. .TP .BI \-w Do not unlink temporary files when finished using them. .TP .BI \-W Lock file when reading or writing. .TP .BI \-x Turn off stone-walling. Stonewalling is a technique used internally to .B Iozone. It is used during the throughput tests. The code starts all threads or processes and then stops them on a barrier. Once they are all ready to start then they are all released at the same time. The moment that any of the threads or processes finish their work then the entire test is terminated and throughput is calculated on the total I/O that was completed up to this point. This ensures that the entire measurement was taken while all of the processes or threads were running in parallel. This flag allows one to turn off the stonewalling and see what happens. .TP .BI \-X\ filename Used to specify a filename that will be used for the write telemetry information. The file contains lines with offset, size, delay_in_milliseconds. Each of these lines are used to perform an I/O operation. This is used when an application's specific I/O operations are known, and one wishes to benchmark the system with this specific application file behavior. .TP .BI \-y\ # Set minimum record size (in Kbytes) for auto mode. One may also specify .BI \-y\ #k (size in Kbytes) or .BI \-y\ #m (size in Mbytes) or .BI \-y\ #g (size in Gbytes). See .BI \-q for maximum record size. .TP .BI \-Y\ filename Used to specify a filename that will be used for the read telemetry information. The file contains lines with offset, size, delay_in_milliseconds. Each of these lines are used to perform an I/O operation. This is used when an application's specific I/O operations are known, and one wishes to benchmark the system with this specific application file behavior. .TP .BI \-z Used in conjunction with .BI \-a to test all possible record sizes. Normally .BI Iozone omits testing of small record sizes for very large files when used in full automatic mode. This option forces .BI Iozone to include the small record sizes in the automatic tests also. .TP .BI \-Z Enable mixing of mmap I/O and file I/O. .TP .BI \-+m\ filename Used to specify a filename that will be used to specify the clients in a distributed measurement. The file contains one line for each client. The fields are space delimited. Field 1 is the client name. Field 2 is the working directory, on the client, where Iozone will run. Field 3 is the path to the executable Iozone on the client. .TP .BI \-+n No retests selected. Used to prevent retests from running. .TP .BI \-+N No truncating or deleting of previous test file before the sequential write test. Useful only after -w is used in previous command to leave the test file in place for reuse. This flag is of limited use, when a single retest is not enough, or to easily control when sequential write retests occur without file truncation or deletion. .TP .BI \-+u Used to enable CPU statistics collection. .TP .BI \-+d Diagnostic mode to troubleshoot a broken file I/O subsystem. .TP .BI \-+p\ percentage_reads Used to set the percentage of threads/processes that will perform read testing in the mixed workload test case. .TP .BI \-+r Enable O_RSYNC | O_SYNC on all testing. .TP .BI \-+l Enable byte range locking. .TP .BI \-+L Enable byte range locking & shared file mode. .TP .BI \-+D Enable O_DSYNC on all testing. .TP .BI \-+t Enable network performance test. Use with -+m .TP .BI \-+A # Enable madvise behavior. 0 = normal, 1=random, 2=sequential, 3=dontneed, 4=willneed .TP .BI \-+B Enable sequential mixed workload testing. .TP .BI \-+T Enable time stamps logging. .TP .BI \-+h Manually set hostname. .TP .BI \-+w # Percentage of data to be de-dupable between files. .SH AUTHOR Original Author: William D. Norcott. wnorcott@us.oracle.com Features & extensions: Don Capps capps@iozone.org iozone3_488/src/current/Android.mk0000444000175000017500000000045213573734166016245 0ustar cappscappsLOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS:= -O3 -Dunix -DANDROID -DHAVE_ANSIC_C -DHAVE_PREAD -DNAME='"linux-arm"' -DLINUX_ARM -Dlinux -lrt -lpthread LOCAL_SRC_FILES:= iozone.c libbif.c LOCAL_MODULE:= iozone LOCAL_CFLAGS +=-Wno-unused-parameter include $(BUILD_EXECUTABLE) iozone3_488/src/current/Android_Readme.md0000544000175000017500000000541013573734166017513 0ustar cappscapps# compiling iozone Assuming you have compiler toolchain installed, just type `make` to get a list of targets then to generate for your iozone for your `` simply type: `make ` **Android specifics** building iozone for Android means doing a cross compilation There is two options then. * cross compiling using Android NDK * cross compiling from android source tree. Due to the disk space required to get an android source tree, this option is valuable only if you are already working with android source tree. **_cross-compiling using Android NDK_** The prerequiste is to download SDK and NDK. SDK cannot easilly dissociated from Android Studio those days. Follow the following steps to get SDK and NDK and cross compile iozone. 1. Prerequesite : Ubuntu LTS release 16.04 or 18.04 or Mac OS 2. Download Android Studio for your platform from https://developer.android.com/studio/ 3. Extract the archive to some place, e.g. your home directory 4. Start android studio 1. on linux: Android Studio needs to be started from a terminal so open a Terminal 2. in terminal type `/android-studio/bin/studio.sh` 3. on Mac OS Android Studio can be launch from lauchpad. if you wish to start it from terminal type `open -a Android\ Studio` 5. keep all the defaults proposed Android Studio. 6. Wait for the download to be ready 7. Download the NDK 1. Select Configure in Android Studio Splash Screen 2. Select SDK Manager 3. Go to system settings Android SDK on the left 4. Select tab SDK Tools 5. Select NDK and apply to install NDK 8. Set NDK environment variable to the ndk-bundle directory 1. e.g. `export NDK=/home/parallels/Android/Sdk/ndk-bundle/` 9. download and extract iozone archive 1. you can opt for extacting only source directory. 1. `mkdir iozone` 2. `cd iozone` 3. `tar -xvf /iozoneX_XXX.tgz -C ./iozone --strip-components 3` 2. or extracting the full archive 1. `tar xvf iozoneX_XXX.tgz` 2. `cd iozoneX_XXX/src/current` 10. build iozone 1. `make android` This will generate 4 version of iozone for different architecture: arm7, arm64, x86, x86_64 2. push the iozone excutable to your Android target e.g. `adb push libs/arm64-v8a/iozone /data/iozone` **_cross-compiling iozone within android source tree_** The Prerequisite is to have an Android source tree availavle. If you do not have it, download it android from Google 1. `cd ` 2. `source ./build/envsetup.sh` 3. `lunch ` 4. `cd /external` 5. `mkdir iozone` 6. `curl http://www.iozone.org/src/current/iozoneX_XXX.tar -o iozoneX_XXX.tar` # assuming this version no proxy, etc` 7. `tar -xvf ./iozoneX_XXX.tar -C ./iozone --strip-components 3` 8. `cd iozone` 9. `mm` iozone3_488/src/current/Application.mk0000544000175000017500000000021213573734166017123 0ustar cappscappsAPP_ABI := armeabi-v7a arm64-v8a x86 x86_64 APP_PLATFORM :=android-24 # mininum Android API level for appropriate multithreading support iozone3_488/src/current/makefile0000444000175000017500000016116113573734166016041 0ustar cappscapps# # Version $Revision: 1.155 $ # # The makefile for building all versions of iozone for all supported # platforms # # Supports: hpux, hpux_no_ansi, hpux-10.1, hpux_no_ansi-10.1, # sppux, sppux-10.1, ghpux, sppux, # convex, FreeBSD, OpenBSD, OSFV3, OSFV4, OSFV5, SCO # SCO_Unixware_gcc,NetBSD,TRU64, Mac OS X CC = cc C89 = c89 GCC = gcc CCS = /usr/ccs/bin/cc NACC = /opt/ansic/bin/cc CFLAGS = S10GCCFLAGS = -m64 S10CCFLAGS = -m64 FLAG64BIT = -m64 NDK_ENV_VAR := $(shell echo $$NDK) NDKBUILD := $(shell which ndk-build) # If your Linux kernel supports preadv and pwritev system calls # and you want iozone to use them, add -DHAVE_PREADV -DHAVE_PWRITEV # to CFLAGS all: @echo "" @echo "You must specify the target. " @echo " -> AIX (32bit) <-" @echo " -> AIX-LF (32bit) <-" @echo " -> AIX64 (32bit) <-" @echo " -> AIX64-LF (32bit) <-" @echo " -> android (arm/x86 32/64bit) <-" @echo " -> bsdi (32bit) <-" @echo " -> convex (32bit) <-" @echo " -> CrayX1 (32bit) <-" @echo " -> dragonfly (32bit) <-" @echo " -> freebsd (32bit) <-" @echo " -> freebsd64 (64bit) <-" @echo " -> generic (32bit) <-" @echo " -> ghpux (32bit) <-" @echo " -> hpuxs-11.0 (simple) (32bit) <-" @echo " -> hpux-11.0w (64bit) <-" @echo " -> hpuxs-11.0w (64bit) <-" @echo " -> hpux-11.0 (32bit) <-" @echo " -> hpux-10.1 (32bit) <-" @echo " -> hpux-10.20 (32bit) <-" @echo " -> hpux (32bit) <-" @echo " -> hpux_no_ansi (32bit) <-" @echo " -> hpux_no_ansi-10.1 (32bit) <-" @echo " -> IRIX (32bit) <-" @echo " -> IRIX64 (64bit) <-" @echo " -> linux (32bit) <-" @echo " -> linux-arm (32bit) <-" @echo " -> linux-AMD64 (64bit) <-" @echo " -> linux-ia64 (64bit) <-" @echo " -> linux-powerpc (32bit) <-" @echo " -> linux-powerpc64 (64bit) <-" @echo " -> linux-sparc (32bit) <-" @echo " -> macosx (32/64bit)<-" @echo " -> netbsd (32bit) <-" @echo " -> netbsd-AMD64 (64bit) <-" @echo " -> openbsd (32bit) <-" @echo " -> openbsd-threads (32bit) <-" @echo " -> OSFV3 (64bit) <-" @echo " -> OSFV4 (64bit) <-" @echo " -> OSFV5 (64bit) <-" @echo " -> linux-S390 (32bit) <-" @echo " -> linux-S390X (64bit) <-" @echo " -> SCO (32bit) <-" @echo " -> SCO_Unixware_gcc (32bit) <-" @echo " -> Solaris (32bit) <-" @echo " -> Solaris-2.6 (32bit) <-" @echo " -> Solaris7gcc (32bit) <-" @echo " -> Solaris8-64 (64bit) <-" @echo " -> Solaris8-64-VXFS (64bit) <-" @echo " -> Solaris10 (32bit) <-" @echo " -> Solaris10cc (64bit) <-" @echo " -> Solaris10gcc (32bit) <-" @echo " -> Solaris10gcc-64 (64bit) <-" @echo " -> sppux (32bit) <-" @echo " -> sppux-10.1 (32bit) <-" @echo " -> sppux_no_ansi-10.1 (32bit) <-" @echo " -> SUA (32bit) <-" @echo " -> TRU64 (64bit) <-" @echo " -> UWIN (32bit) <-" @echo " -> Windows (95/98/NT) (32bit) <-" @echo "" clean: rm -f *.o iozone fileop pit_server rpm: cp ../../iozone*.tar /usr/src/red*/SO* rpmbuild -ba spec.in # # Turn on the optimizer, largefiles, Posix async I/O and threads. # hpux-11.0: iozone_hpux-11.0.o libasync.o libbif.o $(CC) +O3 +Oparallel $(LDFLAGS) iozone_hpux-11.0.o libasync.o \ libbif.o -lpthread -lrt -o iozone # # Turn on wide-mode, the optimizer, largefiles, Posix async I/O and threads. # hpux-11.0w: iozone_hpux-11.0w.o libasyncw.o libbif.o $(CC) +DD64 +O3 $(LDFLAGS) iozone_hpux-11.0w.o libasyncw.o \ libbif.o -lpthread -lrt -o iozone # # Simple build with largefiles, Posix threads and Posix async I/O # hpuxs-11.0: iozone_hpuxs-11.0.o libasync.o libbif.o fileop_hpuxs-11.0.o pit_server.o $(CC) -O $(LDFLAGS) iozone_hpuxs-11.0.o \ libasync.o libbif.o -lpthread -lrt -o iozone $(CC) -O $(LDFLAGS) fileop_hpuxs-11.0.o -o fileop $(CC) -O $(LDFLAGS) pit_server.o -o pit_server # # Simple build with wide-mode, largefiles, Posix threads and Posix async I/O # hpuxs-11.0w: iozone_hpuxs-11.0w.o libasyncw.o libbif.o $(CC) -O +DD64 $(LDFLAGS) iozone_hpuxs-11.0w.o \ libasyncw.o libbif.o -lpthread -lrt -o iozone # # Simple 10.1 build with no threads, no largefiles, no async I/O # hpux-10.1: iozone_hpux-10.1.o libbif.o $(C89) +e -O $(LDFLAGS) iozone_hpux-10.1.o libbif.o -o iozone hpux-10.20: iozone_hpux-10.20.o libbif.o $(C89) +e -O $(LDFLAGS) iozone_hpux-10.20.o libbif.o -o iozone # # Simple generic HP build with no threads, no largefiles, no async I/O # hpux: iozone_hpux.o $(C89) +e -O $(LDFLAGS) iozone_hpux.o libbif.o -o iozone # # GNU HP build with no threads, no largefiles, no async I/O # ghpux: iozone_ghpux.o libbif.o $(GCC) -O $(LDFLAGS) iozone_ghpux.o libbif.o -static -o iozone # # GNU Generic build with no threads, no largefiles, no async I/O # generic: iozone_generic.o libbif.o $(CC) -O $(LDFLAGS) iozone_generic.o libbif.o -o iozone # # No ansii 'C' compiler HP build with no threads, no largefiles, no async I/O # hpux_no_ansi-10.1: iozone_hpux_no-10.1.o libbif.o $(NACC) -O $(LDFLAGS) iozone_hpux_no-10.1.o libbif.o -o iozone # # No ansii 'C' compiler HP build with no threads, no largefiles, no async I/O # hpux_no_ansi: iozone_hpux_no.o libbif.o $(C89) -O $(LDFLAGS) iozone_hpux_no.o libbif.o -o iozone # # GNU 'C' compiler Linux build with threads, largefiles, async I/O # linux: iozone_linux.o libasync.o libbif.o fileop_linux.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_linux.o libasync.o libbif.o -lpthread \ -lrt -o iozone $(CC) -O3 -Dlinux fileop_linux.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' compiler Linux build for powerpc chip with threads, largefiles, async I/O # linux-powerpc: iozone_linux-powerpc.o libbif.o libasync.o fileop_linux-ppc.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_linux-powerpc.o libasync.o \ libbif.o -lpthread -lrt -o iozone $(CC) -O3 -Dlinux fileop_linux-ppc.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' compiler Linux build for sparc chip with threads, largefiles, async I/O # linux-sparc: iozone_linux-sparc.o libbif.o libasync.o fileop_linux.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_linux-sparc.o libasync.o libbif.o \ -lpthread -lrt -o iozone $(CC) -O3 -Dlinux fileop_linux.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' compiler Linux build with threads, largefiles, async I/O # linux-ia64: iozone_linux-ia64.o libbif.o libasync.o fileop_linux-ia64.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_linux-ia64.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O3 -Dlinux fileop_linux-ia64.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' compiler Linux build for powerpc chip with threads, largefiles, async I/O # linux-powerpc64: iozone_linux-powerpc64.o libbif.o libasync.o fileop_linux-ppc64.o pit_server-linux-powerpc64.o $(CC) -O3 -Dunix -DHAVE_ANSIC_C -DSHARED_MEM -DASYNC_IO \ -D_LARGEFILE64_SOURCE -Dlinux \ iozone_linux-powerpc64.o libasync.o libbif.o -lpthread \ -lrt $(FLAG64BIT) -o iozone $(CC) -O3 -Dlinux fileop_linux-ppc64.o $(FLAG64BIT) -o fileop $(CC) -O3 -Dlinux pit_server-linux-powerpc64.o $(FLAG64BIT) -o pit_server # # GNU 'C' compiler Linux build with threads, largefiles, async I/O # linux-arm: iozone_linux-arm.o libbif.o libasync.o fileop_linux-arm.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_linux-arm.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O3 -Dlinux fileop_linux-arm.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' or Clang compiler Linux build with threads, largefiles, async I/O # android: iozone.c makefile Android.mk Application.mk libbif.c ifeq ($(NDK_ENV_VAR)$(NDKBUILD),) $(warning Your NDK environment is not set) $(warning Either add to your path ndk-bundle or define NDK environement variable) $(warning ndk-bundle is likely located within you android sdk e.g. <...>/Android/sdk/ndk-bundle ) $(error e.g. export NDK='/home/me/Android/Sdk/ndk-bundle') endif mkdir -p jni ln -sf ../Android.mk ./jni/Android.mk ln -sf ../Application.mk ./jni/Application.mk ln -sf ../iozone.c ./jni/iozone.c ln -sf ../libbif.c ./jni/libbif.c ifeq ($(NDKBUILD),) ifneq ($(NDK_ENV_VAR),) ${NDK}/ndk-build endif else ${NDKBUILD} endif # # GNU 'C' compiler Linux build with threads, largefiles, async I/O # linux-AMD64: iozone_linux-AMD64.o libbif.o libasync.o fileop_linux-AMD64.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_linux-AMD64.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O3 -Dlinux fileop_linux-AMD64.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' compiler Linux build with S/390, threads, largfiles, async I/O # linux-S390: iozone_linux-s390.o libbif.o libasync.o fileop_linux-s390.o pit_server.o $(CC) -O2 $(LDFLAGS) -lpthread -lrt iozone_linux-s390.o \ libbif.o libasync.o -o iozone $(CC) -O3 -Dlinux fileop_linux-s390.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # GNU 'C' compiler Linux build with S/390, threads, largfiles, async I/O # linux-S390X: iozone_linux-s390x.o libbif.o libasync.o fileop_linux-s390x.o pit_server.o $(CC) -O2 $(LDFLAGS) -lpthread -lrt iozone_linux-s390x.o \ libbif.o libasync.o -o iozone $(CC) -O3 -Dlinux fileop_linux-s390x.o -o fileop $(CC) -O3 -Dlinux pit_server.o -o pit_server # # AIX # I would have built with ASYNC_IO but the AIX machine does not have # POSIX 1003.1b compliant async I/O header files. Has threads, no # largefile support. # AIX: iozone_AIX.o libbif.o fileop_AIX.o $(CC) -O $(LDFLAGS) iozone_AIX.o libbif.o \ -lpthreads -o iozone $(CC) -O -Dlinux fileop_AIX.o -o fileop # # AIX-LF # I would have built with ASYNC_IO but the AIX machine does not have # POSIX 1003.1b compliant async I/O header files. Has threads, and # largefile support. # AIX-LF: iozone_AIX-LF.o libbif.o fileop_AIX-LF.o pit_server.o $(CC) -O $(LDFLAGS) iozone_AIX-LF.o libbif.o \ -lpthreads -o iozone $(CC) -O fileop_AIX-LF.o -o fileop $(CC) -O pit_server.o -o pit_server # AIX64 # This version uses the 64 bit interfaces and is compiled as 64 bit code. # Has threads, async I/O but no largefile support. # AIX64: iozone_AIX64.o libbif.o fileop_AIX64.o libasync.o pit_server.o $(GCC) -maix64 -O3 $(LDFLAGS) iozone_AIX64.o libasync.o \ libbif.o -lpthreads -o iozone $(GCC) -maix64 -O3 $(LDFLAGS) -Dlinux fileop_AIX64.o -o fileop $(GCC) -maix32 -O3 $(LDFLAGS) pit_server.o -o pit_server # # AIX64-LF # This version uses the 64 bit interfaces and is compiled as 64 bit code. # Has threads, async I/O and largefile support. # AIX64-LF: iozone_AIX64-LF.o libbif.o fileop_AIX64-LF.o libasync.o pit_server.o $(GCC) -maix64 -O3 $(LDFLAGS) iozone_AIX64-LF.o libasync.o \ libbif.o -lpthreads -o iozone $(GCC) -maix64 -O3 $(LDFLAGS) -Dlinux fileop_AIX64-LF.o -o fileop $(GCC) -maix32 -O3 $(LDFLAGS) pit_server.o -o pit_server # # IRIX 32 bit build with threads, largefiles, async I/O # This would like to be in 64 bit mode but it hangs whenever in 64 bit mode. # This version uses the 64 bit interfaces but is compiled as 32 bit code # IRIX64: iozone_IRIX64.o libasyncw.o libbif.o $(CC) -32 -O $(LDFLAGS) iozone_IRIX64.o libbif.o \ -lpthread libasyncw.o -o iozone # # IRIX 32 bit build with threads, No largefiles, and async I/O # This version uses the 32 bit interfaces and is compiled as 32 bit code # IRIX: iozone_IRIX.o libasync.o libbif.o $(CC) -O -32 $(LDFLAGS) iozone_IRIX.o libbif.o -lpthread \ libasync.o -o iozone # # CrayX1: 32 bit build with threads, No largefiles, and async I/O # This version uses the 32 bit interfaces and is compiled as 32 bit code # CrayX1: iozone_CrayX1.o libasync.o libbif.o $(CC) -O $(LDFLAGS) iozone_CrayX1.o libbif.o \ -lpthread libasyncw.o -o iozone # # SPP-UX 32 bit build with threads, No largefiles, and No async I/O, # pread extensions # For older SPP-UX machines with 9.05 compatibility # sppux: iozone_sppux.o libbif.o $(NACC) -O $(LDFLAGS) iozone_sppux.o libbif.o \ -Wl,+parallel -lcnx_syscall -lpthread -lail -o iozone # # SPP-UX 32 bit build with threads, No largefiles, and No async I/O, pread # extensions # For Newer SPP-UX machines with 10.01 compatibility # sppux-10.1: iozone_sppux-10.1.o libbif.o $(NACC) -O $(LDFLAGS) iozone_sppux-10.1.o libbif.o \ -lcnx_syscall -Wl,+parallel -lpthread -lail -o iozone # # SPP-UX 32 bit build with threads, No largefiles, and No async I/O, pread # extensions # For Newer SPP-UX machines with 10.01 compatibility, and no ansi 'C' compiler. # sppux_no_ansi-10.1: iozone_sppux_no-10.1.o libbif.o $(CCS) -O $(LDFLAGS) iozone_sppux_no-10.1.o libbif.o \ -Wl,+parallel -lcnx_syscall \ -lpthread -lail -o iozone # # Convex 'C' series 32 bit build with No threads, No largefiles, and No async I/O # convex: iozone_convex.o libbif.o $(CC) -O $(LDFLAGS)iozone_convex.o libbif.o -o iozone # # Solaris 32 bit build with threads, largefiles, and async I/O # Solaris: iozone_solaris.o libasync.o libbif.o fileop_Solaris.o pit_server.o $(CC) -O $(LDFLAGS) iozone_solaris.o libasync.o libbif.o \ -lthread -lpthread -lposix4 -lnsl -laio -lsocket \ -o iozone $(CC) -O fileop_Solaris.o -o fileop $(CC) -O pit_server.o -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o pit_server # # Solaris 32 bit build with threads, largefiles, and async I/O # Solaris7gcc: iozone_solaris7gcc.o libasync7.o libbif7.o $(GCC) -O $(LDFLAGS) iozone_solaris7gcc.o libasync7.o libbif7.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone # # Solaris 32 bit build with threads, largefiles, and async I/O # Solaris10: iozone_solaris10.o libasync10.o libbif10.o fileop_Solaris10.o pit_server.o $(CC) -O $(LDFLAGS) iozone_solaris10.o libasync10.o libbif10.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone $(CC) -O fileop_Solaris10.o -o fileop $(CC) -O pit_server.o -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o pit_server # # Solaris 32 bit build with threads, largefiles, and async I/O # Solaris10cc: iozone_solaris10cc.o libasync10cc.o libbif10cc.o fileop_Solaris10cc.o pit_server.o $(CC) -O $(LDFLAGS) iozone_solaris10cc.o libasync10cc.o libbif10cc.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone $(CC) -O fileop_Solaris10cc.o -o fileop $(CC) -O pit_server.o -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o pit_server # # Solaris 32 bit build with threads, largefiles, and async I/O # Solaris10gcc: iozone_solaris10gcc.o libasync10.o libbif10.o fileop_Solaris10gcc.o pit_server_solaris10gcc.o $(GCC) -O $(LDFLAGS) iozone_solaris10gcc.o libasync10.o libbif10.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone $(GCC) -O fileop_Solaris10gcc.o -o fileop $(GCC) -O pit_server_solaris10gcc.o -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o pit_server # # Solaris 64 bit build with threads, largefiles, and async I/O # Solaris10gcc-64: iozone_solaris10gcc-64.o libasync10-64.o libbif10-64.o fileop_Solaris10gcc-64.o pit_server_solaris10gcc-64.o $(GCC) -O $(LDFLAGS) $(S10GCCFLAGS) iozone_solaris10gcc-64.o libasync10-64.o libbif10-64.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone $(GCC) -O $(S10GCCFLAGS) fileop_Solaris10gcc-64.o -o fileop $(GCC) -O $(S10GCCFLAGS) pit_server_solaris10gcc-64.o -lthread -lpthread -lposix4 \ -lnsl -laio -lsocket -o pit_server # # Solaris 64 bit build with threads, largefiles, and async I/O # Solaris10cc-64: iozone_solaris10cc-64.o libasync10-64.o libbif10-64.o fileop_Solaris10cc-64.o pit_server.o $(CC) -O $(LDFLAGS) $(S10CCFLAGS) iozone_solaris10cc-64.o libasync10-64.o libbif10-64.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone $(CC) -O $(S10CCFLAGS) fileop_Solaris10cc-64.o -o fileop $(CC) -O $(S10CCFLAGS) pit_server.o -lthread -lpthread -lposix4 \ -lnsl -laio -lsocket -o pit_server # # Solaris 2.6 (32 bit) build with no threads, no largefiles, and no async I/O # Solaris-2.6: iozone_solaris-2.6.o libbif.o $(CC) -O $(LDFLAGS) iozone_solaris-2.6.o libbif.o \ -lnsl -laio -lsocket -o iozone # # Solaris 64 bit build with threads, largefiles, and async I/O # Solaris8-64: iozone_solaris8-64.o libasync.o libbif.o $(CC) $(LDFLAGS) -fast -xtarget=generic64 -v iozone_solaris8-64.o \ libasync.o libbif.o -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone # # Solaris 64 bit build with threads, largefiles, async I/O, and Vxfs # Solaris8-64-VXFS: iozone_solaris8-64-VXFS.o libasync.o libbif.o $(CC) $(LDFLAGS) -fast -xtarget=generic64 -v -I/opt/VRTSvxfs/include/ iozone_solaris8-64-VXFS.o libasync.o libbif.o \ -lthread -lpthread -lposix4 -lnsl -laio \ -lsocket -o iozone # # Windows build requires Cygwin development environment. You # can get this from www.cygwin.com # No largefiles, No async I/O # Windows: iozone_windows.o libbif.o fileop_windows.o pit_server_win.o $(GCC) -O $(LDFLAGS) iozone_windows.o libbif.o -o iozone $(GCC) -O $(LDFLAGS) fileop_windows.o -o fileop $(GCC) -O $(LDFLAGS) pit_server_win.o -o pit_server # # Windows build requires SUA development environment. You # can get this from Microsoft # No largefiles, No async I/O # SUA: iozone_sua.o libbif.o fileop_sua.o pit_server_sua.o $(GCC) -O $(LDFLAGS) iozone_sua.o libbif.o -o iozone $(GCC) -O $(LDFLAGS) fileop_sua.o -o fileop $(GCC) -O $(LDFLAGS) pit_server_sua.o -o pit_server # # Uwin build requires UWIN development environment. # No threads, No largefiles, No async I/O # UWIN: iozone_uwin.o libbif.o $(GCC) -O $(LDFLAGS) iozone_uwin.o libbif.o -o iozone # # GNU C compiler BSD/OS build with threads, largefiles, no async I/O # bsdi: iozone_bsdi.o libbif.o fileop_bsdi.o pit_server.o $(CC) -O $(LDFLAGS) iozone_bsdi.o libbif.o -o iozone $(CC) -O fileop_bsdi.o -o fileop $(CC) -O pit_server.o -o pit_server # # GNU C compiler FreeBSD build with no threads, no largefiles, no async I/O # freebsd: iozone_freebsd.o libbif.o fileop_freebsd.o libasync.o pit_server.o $(CC) $(LDFLAGS) iozone_freebsd.o libbif.o -lpthread libasync.o \ -o iozone $(CC) -O fileop_freebsd.o -o fileop $(CC) -O pit_server.o -o pit_server freebsd64: iozone_freebsd64.o libbif.o fileop_freebsd64.o libasync.o pit_server.o $(CC) $(LDFLAGS) iozone_freebsd64.o libbif.o -lpthread libasync.o \ -o iozone $(CC) -O fileop_freebsd64.o -o fileop $(CC) -O pit_server.o -o pit_server # # GNU C compiler DragonFly build with no threads, no largefiles # dragonfly: iozone_dragonfly.o libbif.o fileop_dragonfly.o pit_server.o $(CC) $(LDFLAGS) iozone_dragonfly.o libbif.o -o iozone $(CC) -O fileop_dragonfly.o -o fileop $(CC) -O pit_server.o -o pit_server # # GNU C or Clang compiler MacosX build with no threads, no largefiles, no async I/O # macosx: iozone_macosx.o fileop_macosx.o pit_server.o $(CC) -O3 $(LDFLAGS) iozone_macosx.o libbif.o -o iozone $(CC) -O3 $(LDFLAGS) fileop_macosx.o -o fileop $(CC) -O3 $(LDFLAGS) pit_server.o -o pit_server # # # GNU C compiler OpenBSD build with no threads, no largefiles, no async I/O # openbsd: iozone_openbsd.o libbif.o fileop_openbsd.o pit_server.o $(CC) -O $(LDFLAGS) iozone_openbsd.o libbif.o -o iozone $(CC) -O fileop_openbsd.o -o fileop $(CC) -O pit_server.o -o pit_server # # GNU C compiler OpenBSD build with threads, no largefiles, no async I/O # openbsd-threads: iozone_openbsd-threads.o libbif.o $(CC) -O $(LDFLAGS) -pthread iozone_openbsd-threads.o \ libbif.o -o iozone # # GNU C compiler OSFV3 build # Has threads and async I/O but no largefiles. # OSFV3: iozone_OSFV3.o libbif.o libasync.o $(CC) -O $(LDFLAGS) iozone_OSFV3.o libbif.o \ -lpthreads libasync.o -laio -o iozone # # GNU C compiler OSFV4 build # Has threads and async I/O but no largefiles. # OSFV4: iozone_OSFV4.o libbif.o libasync.o $(CC) -O $(LDFLAGS) iozone_OSFV4.o libbif.o -lpthread \ libasync.o -laio -o iozone # # GNU C compiler OSFV5 build # Has threads and async I/O but no largefiles. # OSFV5: iozone_OSFV5.o libbif.o libasync.o $(CC) -O $(LDFLAGS) iozone_OSFV5.o libbif.o -lpthread \ libasync.o -laio -o iozone # # GNU C compiler TRU64 build # Has threads and async I/O but no largefiles. # TRU64: iozone_TRU64.o libbif.o libasync.o $(CC) -O $(LDFLAGS) iozone_TRU64.o libbif.o -lpthread \ libasync.o -laio -o iozone # # GNU Generic build with no threads, no largefiles, no async I/O # for SCO # Note: Be sure you have the latest patches for SCO's Openserver # or you will get warnings about timer problems. # SCO: iozone_SCO.o libbif.o $(GCC) -O $(LDFLAGS) iozone_SCO.o -lsocket -s libbif.o -o iozone # # GNU build with threads, largefiles, async I/O # for SCO Unixware 5 7.1.1 i386 x86at SCO UNIX SVR5 # Note: Be sure you have the latest patches for SCO's Openserver # or you will get warnings about timer problems. # SCO_Unixware_gcc: iozone_SCO_Unixware_gcc.o libbif.o libasync.o $(GCC) -O $(LDFLAGS) iozone_SCO_Unixware_gcc.o libbif.o libasync.o \ -lsocket -lthread -o iozone # # GNU C compiler NetBSD build with threads, no largefiles, no async I/O # netbsd: iozone_netbsd.o libbif.o libasync.o fileop_netbsd.o pit_server.o $(CC) -O $(LDFLAGS) iozone_netbsd.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O fileop_netbsd.o -o fileop $(CC) -O pit_server.o -o pit_server # # GNU C compiler NetBSD/amd64 build with threads, no largefiles, async I/O # netbsd-AMD64: iozone_netbsd-AMD64.o libbif.o libasync.o fileop_netbsd-AMD64.o pit_server.o $(CC) -O $(LDFLAGS) iozone_netbsd-AMD64.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O fileop_netbsd-AMD64.o -o fileop $(CC) -O pit_server.o -o pit_server # # # # Now for the machine specific stuff # iozone_hpux.o: iozone.c libbif.c @echo "" @echo "Building iozone for HP-UX (9.05)" @echo "" $(C89) +e -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"hpux"' $(CFLAGS) iozone.c -o iozone_hpux.o $(C89) +e -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ $(CFLAGS) libbif.c -o libbif.o iozone_hpux-11.0.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for HP-UX (11.0)" @echo "" $(CC) -c +O3 +Oparallel -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DNAME='"hpux-11.0"' -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) \ iozone.c -o iozone_hpux-11.0.o $(CC) -c +O3 +Oparallel -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) libasync.c -o libasync.o $(CC) -c +O3 +Oparallel -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) libbif.c -o libbif.o iozone_hpux-11.0w.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for HP-UX (11.0w)" @echo "" $(CC) -c +DD64 +O3 -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DNAME='"hpux-11.0w"' -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) iozone.c \ -o iozone_hpux-11.0w.o $(CC) -c +DD64 +O3 -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) libasync.c -o libasyncw.o $(CC) -c +DD64 +O3 -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) libbif.c -o libbif.o iozone_hpuxs-11.0.o: iozone.c libasync.c libbif.c @echo "" @echo "Building simple iozone for HP-UX (11.0)" @echo "" $(CC) -c -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE -DHAVE_ANSIC_C \ -DNAME='"hpuxs-11.0"' -DASYNC_IO -DVXFS -DHAVE_PREAD $(CFLAGS) iozone.c \ -o iozone_hpuxs-11.0.o $(CC) -c -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE -DHAVE_ANSIC_C \ -DASYNC_IO -DVXFS $(CFLAGS) libasync.c -o libasync.o $(CC) -c -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE -DHAVE_ANSIC_C \ -DASYNC_IO -DVXFS $(CFLAGS) libbif.c -o libbif.o fileop_hpuxs-11.0.o: fileop.c @echo "" @echo "Building simple fileop for HP-UX (11.0)" @echo "" $(CC) -c $(CFLAGS) fileop.c -o fileop_hpuxs-11.0.o pit_server_solaris10gcc-64.o: pit_server.c @echo "" @echo "Building the pit_server" @echo "" $(GCC) -c $(CFLAGS) $(S10GCCFLAGS) pit_server.c -o pit_server_solaris10gcc-64.o pit_server.o: pit_server.c @echo "" @echo "Building the pit_server" @echo "" $(CC) -c $(CFLAGS) pit_server.c -o pit_server.o pit_server-linux-powerpc64.o: pit_server.c @echo "" @echo "Building the pit_server" @echo "" $(CC) -c $(CFLAGS) $(FLAG64BIT) pit_server.c -o pit_server-linux-powerpc64.o pit_server_solaris10gcc.o: pit_server.c @echo "" @echo "Building the pit_server" @echo "" $(GCC) -c $(CFLAGS) pit_server.c -o pit_server_solaris10gcc.o pit_server_win.o: pit_server.c @echo "" @echo "Building the pit_server for Windows" @echo "" $(GCC) -c $(CFLAGS) -DWindows pit_server.c -o pit_server_win.o pit_server_sua.o: pit_server.c @echo "" @echo "Building the pit_server for Windows SUA" @echo "" $(GCC) -c $(CFLAGS) -D_SUA_ pit_server.c -o pit_server_sua.o iozone_hpuxs-11.0w.o: iozone.c libasync.c libbif.c @echo "" @echo "Building simple iozone for HP-UX (11.0w)" @echo "" $(CC) -c +DD64 -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DNAME='"hpuxs-11.0w"' -DHAVE_ANSIC_C -DASYNC_IO -DVXFS \ -DHAVE_PREAD $(CFLAGS) iozone.c -o iozone_hpuxs-11.0w.o $(CC) -c +DD64 -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) libasync.c -o libasyncw.o $(CC) -c +DD64 -Dunix -D_LARGEFILE64_SOURCE -D_HPUX_SOURCE \ -DHAVE_ANSIC_C -DASYNC_IO -DVXFS $(CFLAGS) libbif.c -o libbif.o iozone_hpux-10.1.o: iozone.c libbif.c @echo "" @echo "Building iozone for HP-UX (10.1)" @echo "" $(C89) +e -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"hpux-10.1"' $(CFLAGS) iozone.c -o iozone_hpux-10.1.o $(C89) +e -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ $(CFLAGS) libbif.c -o libbif.o iozone_hpux-10.20.o: iozone.c libbif.c @echo "" @echo "Building iozone for HP-UX (10.20)" @echo "" $(C89) +e -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"hpux-10.20"' $(CFLAGS) iozone.c -o iozone_hpux-10.20.o $(C89) +e -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ $(CFLAGS) libbif.c -o libbif.o iozone_ghpux.o: iozone.c libbif.c @echo "" @echo "Building iozone for GCC HP-UX (9.05) " @echo "" $(GCC) -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS $(CFLAGS) iozone.c \ -DNAME='"h=ghpux"' -o iozone_ghpux.o $(GCC) -c -O -Dunix -D_HPUX_SOURCE -DHAVE_ANSIC_C -DNO_THREADS \ $(CFLAGS) libbif.c -o libbif.o iozone_generic.o: iozone.c libbif.c @echo "" @echo "Building iozone Generic " @echo "" $(CC) -c -O -Dgeneric -Dunix -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"Generic"' $(CFLAGS) iozone.c -o iozone_generic.o $(CC) -c -O -Dgeneric -Dunix -DHAVE_ANSIC_C -DNO_THREADS \ $(CFLAGS) libbif.c -o libbif.o iozone_hpux_no.o: iozone.c libbif.c @echo "" @echo "Building iozone for HP-UX (9.05) without ansi compiler" @echo "" $(NACC) -c -O -Dunix -D_HPUX_SOURCE -DNO_THREADS iozone.c \ -DNAME='"hpux_no_ansi"' -o iozone_hpux_no.o $(NACC) -c -O -Dunix -D_HPUX_SOURCE -DNO_THREADS \ libbif.c -o libbif.o iozone_hpux_no-10.1.o: iozone.c @echo "" @echo "Building iozone for HP-UX (10.1) without ansi compiler" @echo "" $(NACC) -c -O -Dunix -D_HPUX_SOURCE -DNO_THREADS iozone.c \ -DNAME='"hpux_no_ansi_10.1"' -o iozone_hpux_no-10.1.o $(NACC) -c -O -Dunix -D_HPUX_SOURCE -DNO_THREADS \ libbif.c -o libbif.o iozone_linux-powerpc.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux PowerPC" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DDONT_HAVE_O_DIRECT \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -DNAME='"linux-powerpc"' -o iozone_linux-powerpc.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_linux-powerpc64.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux PowerPC64" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DNAME='"linux-powerpc64"' \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ $(FLAG64BIT) -o iozone_linux-powerpc64.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c $(FLAG64BIT) -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c $(FLAG64BIT) -o libasync.o iozone_linux-sparc.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux Sparc" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DDONT_HAVE_O_DIRECT \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -DNAME='"linux-sparc"' -o iozone_linux-sparc.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_linux.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux" @echo "" $(CC) -Wmissing-prototypes -Wall -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DHAVE_PREAD \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -DNAME='"linux"' -o iozone_linux.o $(CC) -Wmissing-prototypes -Wall -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -Wmissing-prototypes -Wall -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o fileop_AIX.o: fileop.c @echo "" @echo "Building fileop for AIX" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_AIX.o fileop_AIX-LF.o: fileop.c @echo "" @echo "Building fileop for AIX-LF" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_AIX-LF.o fileop_AIX64.o: fileop.c @echo "" @echo "Building fileop for AIX64" @echo "" $(GCC) -maix64 -c -O3 $(CFLAGS) fileop.c -o fileop_AIX64.o fileop_AIX64-LF.o: fileop.c @echo "" @echo "Building fileop for AIX64-LF" @echo "" $(GCC) -maix64 -c -O3 $(CFLAGS) fileop.c -o fileop_AIX64-LF.o fileop_bsdi.o: fileop.c @echo "" @echo "Building fileop for BSDi" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_bsdi.o fileop_freebsd.o: fileop.c @echo "" @echo "Building fileop for FreeBSD" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_freebsd.o fileop_freebsd64.o: fileop.c @echo "" @echo "Building fileop for FreeBSD64" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_freebsd64.o fileop_dragonfly.o: fileop.c @echo "" @echo "Building fileop for DragonFly" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_dragonfly.o fileop_netbsd.o: fileop.c @echo "" @echo "Building fileop for NetBSD" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_netbsd.o fileop_netbsd-AMD64.o: fileop.c @echo "" @echo "Building fileop for NetBSD/AMD64" @echo "" $(CC) -Wall -c -O $(CFLAGS) fileop.c -o fileop_netbsd-AMD64.o fileop_Solaris.o: fileop.c @echo "" @echo "Building fileop for Solaris" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_Solaris.o fileop_Solaris10.o: fileop.c @echo "" @echo "Building fileop for Solaris10" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_Solaris10.o fileop_Solaris10cc.o: fileop.c @echo "" @echo "Building fileop for Solaris10cc" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_Solaris10cc.o fileop_Solaris10gcc.o: fileop.c @echo "" @echo "Building fileop for Solaris10gcc" @echo "" $(GCC) -c -O $(CFLAGS) fileop.c -o fileop_Solaris10gcc.o fileop_Solaris10gcc-64.o: fileop.c @echo "" @echo "Building fileop for Solaris10gcc-64" @echo "" $(GCC) -c -O $(CFLAGS) $(S10GCCFLAGS) fileop.c -o fileop_Solaris10gcc-64.o fileop_Solaris10cc-64.o: fileop.c @echo "" @echo "Building fileop for Solaris10cc-64" @echo "" $(CC) -c -O $(CFLAGS) $(S10CCFLAGS) fileop.c -o fileop_Solaris10cc-64.o fileop_linux.o: fileop.c @echo "" @echo "Building fileop for Linux" @echo "" $(CC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux.o fileop_openbsd.o: fileop.c @echo "" @echo "Building fileop for OpenBSD" @echo "" $(CC) -Wall -c -O $(CFLAGS) fileop.c -o fileop_openbsd.o fileop_macosx.o: fileop.c @echo "" @echo "Building fileop for MAC OS X" @echo "" $(CC) -Wall -c -O3 -DIOZ_macosx $(CFLAGS) fileop.c -o fileop_macosx.o fileop_linux-ia64.o: fileop.c @echo "" @echo "Building fileop for Linux-ia64" @echo "" $(CC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux-ia64.o fileop_linux-ppc.o: fileop.c @echo "" @echo "Building fileop for Linux-powerpc" @echo "" $(CC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux-ppc.o fileop_linux-ppc64.o: fileop.c @echo "" @echo "Building fileop for Linux-powerpc64" @echo "" $(CC) -Wall -c -O3 $(CFLAGS) $(FLAG64BIT) fileop.c -o fileop_linux-ppc64.o fileop_linux-AMD64.o: fileop.c @echo "" @echo "Building fileop for Linux-AMD64" @echo "" $(CC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux-AMD64.o fileop_linux-arm.o: fileop.c @echo "" @echo "Building fileop for Linux-arm" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux-arm.o fileop_android.o: fileop.c @echo "" @echo "Building fileop for Android" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) $(ANDROID_CFLAGS) fileop.c -o fileop_android.o fileop_linux-s390.o: fileop.c @echo "" @echo "Building fileop for Linux-S390" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux-s390.o fileop_linux-s390x.o: fileop.c @echo "" @echo "Building fileop for Linux-s390x" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) fileop.c -o fileop_linux-s390x.o fileop_windows.o: fileop.c @echo "" @echo "Building fileop for Windows" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) -DWindows fileop.c -o fileop_windows.o fileop_sua.o: fileop.c @echo "" @echo "Building fileop for Windows SUA" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) -D_SUA_ fileop.c -o fileop_sua.o iozone_linux-ia64.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux-ia64" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DNAME='"linux-ia64"' \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -o iozone_linux-ia64.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_linux-arm.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux-arm" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DHAVE_PREAD \ -DNAME='"linux-arm"' -DLINUX_ARM -DSHARED_MEM \ -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -o iozone_linux-arm.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_android.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Android" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DHAVE_PREAD \ -DNAME='"android"' -DLINUX_ARM -DANDROID -DSHARED_MEM \ -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) $(ANDROID_CFLAGS) iozone.c \ -o iozone_android.o $(CC) -c -O3 -Dunix -DANDROID -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) $(ANDROID_CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DANDROID -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) $(ANDROID_CFLAGS) libasync.c -o libasync.o iozone_linux-AMD64.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux-AMD64" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DNAME='"linux-AMD64"' \ -D__AMD64__ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE \ -DHAVE_PREAD $(CFLAGS) iozone.c -o iozone_linux-AMD64.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_linux-s390.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux-s390" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DHAVE_PREAD \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -DNAME='"linux-s390"' -o iozone_linux-s390.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DSHARED_MEM -Dlinux \ -D_LARGEFILE64_SOURCE $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_linux-s390x.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for Linux-s390x" @echo "" $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DHAVE_PREAD \ -DSHARED_MEM -Dlinux -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -DNAME='"linux-s390x"' -o iozone_linux-s390x.o $(CC) -c -O3 -Dunix -DHAVE_ANSIC_C -DSHARED_MEM -Dlinux \ -D_LARGEFILE64_SOURCE $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_AIX.o: iozone.c libbif.c @echo "" @echo "Building iozone for AIX" @echo "" $(CC) -c -O -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DNAME='"AIX"' -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_AIX.o $(CC) -c -O -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone_AIX-LF.o: iozone.c libbif.c @echo "" @echo "Building iozone for AIX with Large files" @echo "" $(CC) -c -O -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DSHARED_MEM -D_LARGEFILE64_SOURCE -D_LARGE_FILES \ -DNAME='"AIX-LF"' $(CFLAGS) iozone.c -o iozone_AIX-LF.o $(CC) -c -O -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DSHARED_MEM -D_LARGEFILE64_SOURCE -D_LARGE_FILES \ $(CFLAGS) libbif.c -o libbif.o iozone_AIX64.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for AIX64" @echo "" $(GCC) -maix64 -c -O3 -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -DNAME='"AIX64"' -DSHARED_MEM \ $(CFLAGS) iozone.c -o iozone_AIX64.o $(GCC) -maix64 -c -O3 -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o $(GCC) -maix64 -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ $(CFLAGS) libasync.c -o libasync.o iozone_AIX64-LF.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for AIX64 with Large files" @echo "" $(GCC) -maix64 -c -O3 -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -DNAME='"AIX64-LF"' -DSHARED_MEM \ -D_LARGEFILE64_SOURCE -D_LARGE_FILES \ $(CFLAGS) iozone.c -o iozone_AIX64-LF.o $(GCC) -maix64 -c -O3 -D__AIX__ -D_NO_PROTO -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -DSHARED_MEM -D_LARGEFILE64_SOURCE -D_LARGE_FILES \ $(CFLAGS) libbif.c -o libbif.o $(GCC) -maix64 -c -O3 -Dunix -Dlinux -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE -D_LARGE_FILES \ $(CFLAGS) libasync.c -o libasync.o iozone_solaris.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for Solaris" @echo "" $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris"' $(CFLAGS) iozone.c -o iozone_solaris.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) libasync.c -o libasync.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) libbif.c -o libbif.o iozone_solaris7gcc.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for Solaris7gcc" @echo "" $(GCC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris7gcc"' $(CFLAGS) libasync.c -o libasync7.o $(GCC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) libbif.c -o libbif7.o $(GCC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris7gcc"' $(CFLAGS) iozone.c -o iozone_solaris7gcc.o iozone_solaris10.o: iozone.c libbif.c @echo "" @echo "Building iozone for Solaris10" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) libbif.c -o libbif10.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10"' $(CFLAGS) libasync.c -o libasync10.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO -Dstudio11 \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10"' $(CFLAGS) iozone.c -o iozone_solaris10.o iozone_solaris10cc.o: iozone.c libbif.c @echo "" @echo "Building iozone for Solaris10cc" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) libbif.c -o libbif10cc.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10"' $(CFLAGS) libasync.c -o libasync10cc.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO -Dstudio11 \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10"' $(CFLAGS) iozone.c -o iozone_solaris10cc.o iozone_solaris10gcc.o: iozone.c libbif.c @echo "" @echo "Building iozone for Solaris10gcc" @echo "" $(GCC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) libbif.c -o libbif10.o $(GCC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10gcc"' $(CFLAGS) libasync.c -o libasync10.o $(GCC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10gcc"' $(CFLAGS) iozone.c -o iozone_solaris10gcc.o iozone_solaris10gcc-64.o: iozone.c libbif.c @echo "" @echo "Building iozone for Solaris10gcc-64" @echo "" $(GCC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) $(S10GCCFLAGS) libbif.c -o libbif10-64.o $(GCC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10gcc-64"' $(CFLAGS) $(S10GCCFLAGS) libasync.c -o libasync10-64.o $(GCC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10gcc-64"' $(CFLAGS) $(S10GCCFLAGS) iozone.c -o iozone_solaris10gcc-64.o iozone_solaris10cc-64.o: iozone.c libbif.c @echo "" @echo "Building iozone for Solaris10cc-64" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ $(CFLAGS) $(S10CCFLAGS) libbif.c -o libbif10-64.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D__LP64__ \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10cc-64"' $(CFLAGS) $(S10CCFLAGS) libasync.c -o libasync10-64.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO -Dstudio11 \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Dsolaris \ -DNAME='"Solaris10cc-64"' $(CFLAGS) $(S10CCFLAGS) iozone.c -o iozone_solaris10cc-64.o # # -DSHARED_MEM -Dsolaris libasync.c -o libasync.o # -DSHARED_MEM -Dsolaris iozone.c -o iozone_solaris.o # iozone_solaris-2.6.o: iozone.c libbif.c @echo "" @echo "Building iozone for Solaris-2.6" @echo "" $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"Solaris-2.6"' -Dsolaris $(CFLAGS) iozone.c -o iozone_solaris-2.6.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C \ -Dsolaris $(CFLAGS) libbif.c -o libbif.o iozone_solaris8-64.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for Solaris8-64" @echo "" $(CC) -fast -xtarget=generic64 -v -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D__LP64__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ -DNAME='"Solaris8-64"' -Dsolaris -DHAVE_PREAD \ $(CFLAGS) iozone.c -o iozone_solaris8-64.o $(CC) -fast -xtarget=generic64 -v -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D__LP64__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ -Dsolaris -DHAVE_PREAD $(CFLAGS) libasync.c -o libasync.o $(CC) -fast -xtarget=generic64 -v -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -D__LP64__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ -Dsolaris -DHAVE_PREAD $(CFLAGS) libbif.c -o libbif.o iozone_solaris8-64-VXFS.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for Solaris8-64-VXFS" @echo "" $(CC) -fast -xtarget=generic64 -v -c -I/opt/VRTSvxfs/include/ -Dunix \ -DVXFS -DHAVE_ANSIC_C -DASYNC_IO \ -D__LP64__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ -DNAME='"Solaris8-64"' -Dsolaris -DHAVE_PREAD \ $(CFLAGS) iozone.c -o iozone_solaris8-64-VXFS.o $(CC) -fast -xtarget=generic64 -v -c -I/opt/VRTSvxfs/include/ -Dunix \ -DVXFS -DHAVE_ANSIC_C -DASYNC_IO \ -D__LP64__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ -Dsolaris -DHAVE_PREAD $(CFLAGS) libasync.c -o libasync.o $(CC) -fast -xtarget=generic64 -v -c -I/opt/VRTSvxfs/include/ -Dunix \ -DVXFS -DHAVE_ANSIC_C -DASYNC_IO \ -D__LP64__ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ -Dsolaris -DHAVE_PREAD $(CFLAGS) libbif.c -o libbif.o iozone_windows.o: iozone.c libasync.c libbif.c fileop.c @echo "" @echo "Building iozone for Windows (No async I/O)" @echo "" $(GCC) -c -O -Dunix -DHAVE_ANSIC_C -DNO_MADVISE \ -DWindows $(CFLAGS) iozone.c \ -o iozone_windows.o $(GCC) -c -O -Dunix -DHAVE_ANSIC_C -DNO_MADVISE \ -DWindows $(CFLAGS) libbif.c -o libbif.o # -D_SUA_ $(CFLAGS) -DDONT_HAVE_O_DIRECT iozone.c \ iozone_sua.o: iozone.c libasync.c libbif.c fileop.c @echo "" @echo "Building iozone for Windows SUA (No async I/O)" @echo "" $(GCC) -c -O -Dunix -DHAVE_ANSIC_C -D_XOPEN_SOURCE -DNO_MADVISE \ -D_SUA_ $(CFLAGS) iozone.c \ -DNAME='"Windows SUA"' -o iozone_sua.o $(GCC) -c -O -Dunix -D_SUA_ -D_XOPEN_SOURCE -DHAVE_ANSIC_C \ -DNO_MADVISE $(CFLAGS) libbif.c -o libbif.o iozone_uwin.o: iozone.c libbif.c @echo "" @echo "Building iozone for UWIN (No threads, No async I/O)" @echo "" $(GCC) -c -O -DUWIN -Dunix -DHAVE_ANSIC_C -DNO_THREADS -DNO_MADVISE \ -DNAME='"UWIN"' -DSHARED_MEM -DWindows $(CFLAGS) iozone.c -o iozone_uwin.o $(GCC) -c -O -DUWIN -Dunix -DHAVE_ANSIC_C -DNO_THREADS -DNO_MADVISE \ -DSHARED_MEM -DWindows $(CFLAGS) libbif.c -o libbif.o iozone_IRIX64.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for IRIX64" @echo "" $(CC) -32 -O -c -Dunix -DHAVE_ANSIC_C -D_LARGEFILE64_SOURCE -DASYNC_IO \ -DNAME='"IRIX64"' -DIRIX64 -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_IRIX64.o $(CC) -32 -O -c -Dunix -DHAVE_ANSIC_C -D_LARGEFILE64_SOURCE -DASYNC_IO \ -DIRIX64 -DSHARED_MEM $(CFLAGS) libasync.c -o libasyncw.o $(CC) -32 -O -c -Dunix -DHAVE_ANSIC_C -D_LARGEFILE64_SOURCE -DASYNC_IO \ -DIRIX64 -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone_IRIX.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for IRIX" @echo "" $(CC) -O -32 -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -DNAME='"IRIX"' -DIRIX -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_IRIX.o $(CC) -O -32 -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -DIRIX -DSHARED_MEM $(CFLAGS) libasync.c -o libasync.o $(CC) -O -32 -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -DIRIX -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone_CrayX1.o: iozone.c libasync.c libbif.c @echo "" @echo "Building iozone for CrayX1" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DNAME='"CrayX1"' -DIRIX64 -DSHARED_MEM -D__CrayX1__ \ $(CFLAGS) iozone.c -o iozone_CrayX1.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DIRIX64 -DSHARED_MEM -D__CrayX1__ \ $(CFLAGS) libasync.c -o libasyncw.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DIRIX64 -DSHARED_MEM -D__CrayX1__ $(CFLAGS) libbif.c \ -o libbif.o iozone_sppux.o: iozone.c libbif.c @echo "" @echo "Building iozone for SPP-UX using Convex compiler" @echo "" $(NACC) -c -O -Dunix -D_HPUX_SOURCE -D__convex_spp \ -DNAME='"sppux"' -Wl,+parallel -DHAVE_ANSIC_C -DHAVE_PREAD \ -DHAVE_PREADV $(CFLAGS) iozone.c -o iozone_sppux.o $(NACC) -O -Dunix -D_HPUX_SOURCE -D__convex_spp \ -Wl,+parallel -DHAVE_ANSIC_C -DHAVE_PREAD -DHAVE_PREADV \ $(CFLAGS) libbif.c -o libbif.o iozone_sppux-10.1.o: iozone.c libbif.c @echo "" @echo "Building iozone for SPP-UX using HP ansic compiler" @echo "" $(NACC) -c -O -Dunix -D_HPUX_SOURCE -D__convex_spp \ -DHAVE_ANSIC_C -DHAVE_PREAD -DHAVE_PREADV $(CFLAGS) iozone.c \ -DNAME='"sppux-10.1"' -Wl,+parallel -o iozone_sppux-10.1.o $(NACC) -c -O -Dunix -D_HPUX_SOURCE -D__convex_spp \ -DHAVE_ANSIC_C -DHAVE_PREAD -DHAVE_PREADV \ $(CFLAGS) libbif.c -Wl,+parallel -o libbif.o iozone_sppux_no-10.1.o: iozone.c libbif.c @echo "" @echo "Building iozone for SPP-UX no ANSI c compiler" @echo "" $(CCS) -c -O -Dunix -D_HPUX_SOURCE -D__convex_spp \ -DNAME='"sppux_no_ansi_10.1"' -Wl,+parallel -DHAVE_PREAD \ -DHAVE_PREADV $(CFLAGS) iozone.c -o iozone_sppux_no-10.1.o $(CCS) -c -O -Dunix -D_HPUX_SOURCE -D__convex_spp \ -Wl,+parallel -DHAVE_PREAD -DHAVE_PREADV $(CFLAGS) \ libbif.c -o libbif.o iozone_convex.o: iozone.c libbif.c @echo "" @echo "Building iozone for Convex 'C' series" @echo "" $(CC) -c -O -Dunix -DNO_THREADS -Dbsd4_2 $(CFLAGS) iozone.c \ -DNAME='"Convex"' -o iozone_convex.o $(CC) -c -O -Dunix -DNO_THREADS -Dbsd4_2 \ $(CFLAGS) libbif.c -o libbif.o iozone_bsdi.o: iozone.c libbif.c @echo "" @echo "Build iozone for BSD/OS" @echo "" $(CC) -c -O -Dunix -Dbsd4_4 -DHAVE_ANSIC_C \ -DNAME='"bsdi"' $(CFLAGS) iozone.c -o iozone_bsdi.o $(CC) -c -O -Dunix -Dbsd4_4 -DHAVE_ANSIC_C \ $(CFLAGS) libbif.c -o libbif.o iozone_freebsd.o: iozone.c libbif.c libasync.c @echo "" @echo "Build iozone for FreeBSD" @echo "" $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO \ -DHAVE_PREAD -DNAME='"freebsd"' -DSHARED_MEM \ $(CFLAGS) iozone.c -o iozone_freebsd.o $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO \ -DSHARED_MEM -DHAVE_PREAD $(CFLAGS) libbif.c \ -o libbif.o $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO \ -DSHARED_MEM -DHAVE_PREAD $(CFLAGS) libasync.c \ -o libasync.o iozone_freebsd64.o: iozone.c libbif.c libasync.c @echo "" @echo "Build iozone for FreeBSD64" @echo "" $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO \ -DHAVE_PREAD -DNAME='"freebsd"' -DSHARED_MEM \ $(CFLAGS) iozone.c -o iozone_freebsd64.o $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO \ -DSHARED_MEM -DHAVE_PREAD $(CFLAGS) libbif.c \ -o libbif.o $(CC) -c ${CFLAGS} -DFreeBSD -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DASYNC_IO \ -DSHARED_MEM -DHAVE_PREAD $(CFLAGS) libasync.c \ -o libasync.o iozone_dragonfly.o: iozone.c libbif.c @echo "" @echo "Build iozone for DragonFly" @echo "" $(CC) -c ${CFLAGS} -D__DragonFly__ -Dunix -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"dragonfly"' -DSHARED_MEM -DHAVE_PREAD -DHAVE_PREADV \ $(CFLAGS) iozone.c -o iozone_dragonfly.o $(CC) -c ${CFLAGS} -D__DragonFly__ -Dunix -DHAVE_ANSIC_C -DNO_THREADS \ -DSHARED_MEM -DHAVE_PREAD -DHAVE_PREADV $(CFLAGS) libbif.c \ -o libbif.o iozone_macosx.o: iozone.c libbif.c @echo "" @echo "Build iozone for MacOSX" @echo "" $(CC) -c -O3 -Dunix -Dbsd4_2 -DIOZ_macosx -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"macosx"' -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_macosx.o $(CC) -c -O3 -Dunix -Dbsd4_2 -DIOZ_macosx -DHAVE_ANSIC_C -DNO_THREADS \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone_openbsd.o: iozone.c libbif.c @echo "" @echo "Build iozone for OpenBSD" @echo "" $(CC) -c -O -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"openbsd"' -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_openbsd.o $(CC) -c -O -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DNO_THREADS \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone_openbsd-threads.o: iozone.c libbif.c @echo "" @echo "Build iozone for OpenBSD with threads" @echo "" $(CC) -c -O -pthread -Dunix -Dbsd4_4 -DHAVE_ANSIC_C \ -DNAME='"openbsd-threads"' $(CFLAGS) iozone.c \ -o iozone_openbsd-threads.o $(CC) -c -O -pthread -Dunix -Dbsd4_4 -DHAVE_ANSIC_C \ $(CFLAGS) libbif.c -o libbif.o iozone_OSFV3.o: iozone.c libbif.c @echo "" @echo "Build iozone for OSFV3" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV3 \ -DNAME='"OSFV3"' -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) iozone.c \ -o iozone_OSFV3.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV3 \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libbif.c -o libbif.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV3 \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o iozone_OSFV4.o: iozone.c libbif.c @echo "" @echo "Build iozone for OSFV4" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV4 \ -DNAME='"OSFV4"' -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) iozone.c \ -o iozone_OSFV4.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV4 \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libbif.c -o libbif.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV4 \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o iozone_OSFV5.o: iozone.c libbif.c @echo "" @echo "Build iozone for OSFV5" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV5 \ -DNAME='"OSFV5"' -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) iozone.c \ -o iozone_OSFV5.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV5 \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libbif.c -o libbif.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV5 \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o iozone_TRU64.o: iozone.c libbif.c @echo "" @echo "Build iozone for TRU64" @echo "" $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV5 -DTRU64 -DHAVE_PREAD \ -DNAME='"TRU64"' -DNO_PRINT_LLD -DOSF_64 -pthread $(CFLAGS) iozone.c \ -o iozone_TRU64.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV5 -DHAVE_PREAD \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libbif.c -o libbif.o $(CC) -O -c -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DOSFV5 -DHAVE_PREAD \ -DNO_PRINT_LLD -DOSF_64 $(CFLAGS) libasync.c -o libasync.o iozone_SCO.o: iozone.c libbif.c @echo "" @echo "Building iozone SCO " @echo "" $(GCC) -c -O -DSCO -Dunix -DHAVE_ANSIC_C -DNO_THREADS -DNO_MADVISE \ -DNAME='"SCO"' $(CFLAGS) iozone.c -o iozone_SCO.o $(GCC) -c -O -DSCO -Dunix -DHAVE_ANSIC_C -DNO_THREADS -DNO_MADVISE \ $(CFLAGS) libbif.c -o libbif.o iozone_SCO_Unixware_gcc.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone SCO_Unixware_gcc " @echo "" $(GCC) -c -O -DSCO_Unixware_gcc -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -D_LARGEFILE64_SOURCE $(CFLAGS) iozone.c \ -DNAME='"SCO_Unixware_gcc"' -o iozone_SCO_Unixware_gcc.o $(GCC) -c -O -DSCO_Unixware_gcc -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -D_LARGEFILE64_SOURCE $(CFLAGS) libbif.c -o libbif.o $(GCC) -c -O -DSCO_Unixware_gcc -Dunix -DHAVE_ANSIC_C \ -DASYNC_IO -D_LARGEFILE64_SOURCE $(CFLAGS) libasync.c -o libasync.o iozone_netbsd.o: iozone.c libbif.c @echo "" @echo "Building iozone NetBSD " @echo "" $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DNAME='"netbsd"' \ -DSHARED_MEM \ -DHAVE_PREAD $(CFLAGS) iozone.c -o iozone_netbsd.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ $(CFLAGS) libasync.c -o libasync.o iozone_netbsd-AMD64.o: iozone.c libbif.c libasync.c @echo "" @echo "Building iozone for NetBSD/amd64" @echo "" $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO -DNAME='"netbsd-AMD64"' \ -D__AMD64__ -DSHARED_MEM \ -DHAVE_PREAD $(CFLAGS) iozone.c -o iozone_netbsd-AMD64.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o $(CC) -c -O -Dunix -DHAVE_ANSIC_C -DASYNC_IO \ $(CFLAGS) libasync.c -o libasync.o $(CC) -c -O -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DNO_THREADS \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone3_488/src/current/libasync.c0000444000175000017500000010323313573734166016305 0ustar cappscapps/* * Library for Posix async read operations with hints. * Author: Don Capps * Company: Iozone * Date: 4/24/1998 * * Two models are supported. First model is a replacement for read() where the async * operations are performed and the requested data is bcopy()-ed back into the users * buffer. The second model is a new version of read() where the caller does not * supply the address of the buffer but instead is returned an address to the * location of the data. The second model eliminates a bcopy from the path. * * To use model #1: * 1. Call async_init(&pointer_on_stack,fd,direct_flag); * The fd is the file descriptor for the async operations. * The direct_flag sets VX_DIRECT * * 2. Call async_read(gc, fd, ubuffer, offset, size, stride, max, depth) * Where: * gc ............ is the pointer on the stack * fd ............ is the file descriptor * ubuffer ....... is the address of the user buffer. * offset ........ is the offset in the file to begin reading * size .......... is the size of the transfer. * stride ........ is the distance, in size units, to space the async reads. * max ........... is the max size of the file to be read. * depth ......... is the number of async operations to perform. * * 3. Call end_async(gc) when finished. * Where: * gc ............ is the pointer on the stack. * * To use model #2: * 1. Call async_init(&pointer_on_stack,fd,direct_flag); * The fd is the file descriptor for the async operations. * The direct_flag sets VX_DIRECT * 2. Call async_read(gc, fd, &ubuffer, offset, size, stride, max, depth) * Where: * gc ............ is the pointer on the stack * fd ............ is the file descriptor * ubuffer ....... is the address of a pointer that will be filled in * by the async library. * offset ........ is the offset in the file to begin reading * size .......... is the size of the transfer. * stride ........ is the distance, in size units, to space the async reads. * max ........... is the max size of the file to be read. * depth ......... is the number of async operations to perform. * * 3. Call async_release(gc) when finished with the data that was returned. * This allows the async library to reuse the memory that was filled in * and returned to the user. * * 4. Call end_async(gc) when finished. * Where: * gc ............ is the pointer on the stack. * * To use model #1: (WRITES) * 1. Call async_init(&pointer_on_stack,fd,direct_flag); * The fd is the file descriptor for the async operations. * * 2. Call async_write(gc, fd, ubuffer, size, offset, depth) * Where: * gc ............ is the pointer on the stack * fd ............ is the file descriptor * ubuffer ....... is the address of the user buffer. * size .......... is the size of the transfer. * offset ........ is the offset in the file to begin reading * depth ......... is the number of async operations to perform. * * 4. Call end_async(gc) when finished. * Where: * gc ............ is the pointer on the stack. * * Notes: * The intended use is to replace calls to read() with calls to * async_read() and allow the user to make suggestions on * what kind of async read-ahead would be nice to have. * The first transfer requested is guarenteed to be complete * before returning to the caller. The async operations will * be started and will also be guarenteed to have completed * if the next call specifies its first request to be one * that was previously performed with an async operation. * * The async_read_no_copy() function allows the async operations * to return the data to the user and not have to perform * a bcopy of the data back into the user specified buffer * location. This model is faster but assumes that the user * application has been modified to work with this model. * * The async_write() is intended to enhance the performance of * initial writes to a file. This is the slowest case in the write * path as it must perform meta-data allocations and wait. */ #include #include #if defined(_LARGEFILE64_SOURCE) && !defined(__LP64__) # define aio_error aio_error64 # define aio_return aio_return64 # define aio_read aio_read64 # define aio_cancel aio_cancel64 # define aio_write aio_write64 #endif #if defined(solaris) || defined(linux) || defined(SCO_Unixware_gcc) || defined(__NetBSD__) #else #include #endif #include #include #ifndef bsd4_4 #include #endif #ifdef VXFS #include #endif #if defined(OSFV5) || defined(linux) #include #endif #if defined(linux) #include #include #include #endif #if (defined(solaris) && defined(__LP64__)) || defined(__s390x__) || defined(__FreeBSD__) || defined(__NetBSD__) /* If we are building for 64-bit Solaris, all functions that return pointers * must be declared before they are used; otherwise the compiler will assume * that they return ints and the top 32 bits of the pointer will be lost, * causing segmentation faults. The following includes take care of this. * It should be safe to add these for all other OSs too, but we're only * doing it for Solaris now in case another OS turns out to be a special case. */ #include #include #include /* For the BSD string functions */ #endif static void mbcopy(const char *source, char *dest, size_t len); #if !defined(solaris) && !defined(off64_t) && !defined(_OFF64_T) && !defined(__off64_t_defined) && !defined(SCO_Unixware_gcc) # if defined(bsd4_4) typedef off_t off64_t; # else typedef long long off64_t; # endif #endif #if defined(OSFV5) #include #endif extern long long page_size; extern int one; /* * Internal cache entrys. Each entry on the global * cache, pointed to by async_init(gc) will be of * this structure type. */ static const char version[] = "Libasync Version $Revision: 3.34 $"; struct cache_ent { #if defined(_LARGEFILE64_SOURCE) && defined(__CrayX1__) aiocb64_t myaiocb; /* For use in large file mode */ #elif defined(_LARGEFILE64_SOURCE) && !defined(__LP64__) struct aiocb64 myaiocb; /* For use in large file mode */ #else struct aiocb myaiocb; #endif long long fd; /* File descriptor */ long long size; /* Size of the transfer */ struct cache_ent *forward; /* link to next element on cache list */ struct cache_ent *back; /* link to previous element on the cache list */ long long direct; /* flag to indicate if the buffer should be */ /* de-allocated by library */ char *real_address; /* Real address to free */ volatile void *oldbuf; /* Used for firewall to prevent in flight */ /* accidents */ int oldfd; /* Used for firewall to prevent in flight */ /* accidents */ size_t oldsize; /* Used for firewall to prevent in flight */ /* accidents */ }; /* * Head of the cache list */ struct cache { struct cache_ent *head; /* Head of cache list */ struct cache_ent *tail; /* tail of cache list */ struct cache_ent *inuse_head; /* head of in-use list */ long long count; /* How many elements on the cache list */ struct cache_ent *w_head; /* Head of cache list */ struct cache_ent *w_tail; /* tail of cache list */ long long w_count; /* How many elements on the write list */ }; long long max_depth; extern int errno; static struct cache_ent *alloc_cache(); static struct cache_ent *incache(); #ifdef HAVE_ANSIC_C void async_init(struct cache **,int, int); int async_suspend(struct cache_ent *); void end_async(struct cache *); void takeoff_cache(struct cache *, struct cache_ent *); void del_cache(struct cache *); void putoninuse(struct cache *,struct cache_ent *); void takeoffinuse(struct cache *); struct cache_ent * allocate_write_buffer( struct cache *, long long , long long ,long long, long long, long long, long long, char *, char *); void async_put_on_write_queue(struct cache *, struct cache_ent *); void async_write_finish(struct cache *); void async_wait_for_write(struct cache *); int async_read(struct cache *, long long , char *, off64_t, long long, long long, off64_t, long long); struct cache_ent * alloc_cache(struct cache *gc,long long fd,off64_t offset,long long size,long long op); struct cache_ent * incache(struct cache *, long long, off64_t, long long); int async_read_no_copy(struct cache *, long long, char **, off64_t, long long, long long, off64_t, long long); void async_release(struct cache *gc); size_t async_write(struct cache *,long long, char *, long long, off64_t, long long); size_t async_write_no_copy(struct cache *gc,long long fd,char *buffer,long long size,long long offset,long long depth,char *free_addr); #else void async_init(); void end_async(); int async_suspend(); int async_read(); void async_release(); struct cache_ent *allocate_write_buffer(); size_t async_write(); void async_wait_for_write(); void async_put_on_write_queue(); void async_write_finish(); struct cache_ent * alloc_cache(); #endif /* On Solaris _LP64 will be defined by if we're compiling * as a 64-bit binary. Make sure that __LP64__ gets defined in this case, * too -- it should be defined on the compiler command line, but let's * not rely on this. */ #if defined(_LP64) #if !defined(__LP64__) #define __LP64__ #endif #endif /***********************************************/ /* Initialization routine to setup the library */ /***********************************************/ #ifdef HAVE_ANSIC_C void async_init(struct cache **gc,int fd,int flag) #else void async_init(gc,fd,flag) struct cache **gc; int fd; int flag; #endif { #ifdef VXFS if(flag) ioctl(fd,VX_SETCACHE,VX_DIRECT); #endif if(*gc) { printf("Warning calling async_init two times ?\n"); return; } *gc=(struct cache *)malloc((size_t)sizeof(struct cache)); if(*gc == 0) { printf("Malloc failed\n"); exit(174); } bzero(*gc,sizeof(struct cache)); #if defined(__AIX__) || defined(SCO_Unixware_gcc) max_depth=500; #else max_depth=sysconf(_SC_AIO_MAX); #endif } /***********************************************/ /* Tear down routine to shutdown the library */ /***********************************************/ #ifdef HAVE_ANSIC_C void end_async(struct cache *gc) #else void end_async(gc) struct cache *gc; #endif { del_cache(gc); if(gc && (gc->w_head !=NULL)) async_write_finish(gc); if(gc != NULL) free((void *)gc); gc = NULL; } /***********************************************/ /* Wait for a request to finish */ /***********************************************/ #ifdef HAVE_ANSIC_C int async_suspend(struct cache_ent *ce) #else int async_suspend(ce) struct cache_ent *ce; #endif { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ const struct aiocb * const cblist[1] = {&ce->myaiocb}; #else const struct aiocb64 * const cblist[1] = {&ce->myaiocb}; #endif #else const struct aiocb * const cblist[1] = {&ce->myaiocb}; #endif #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ return aio_suspend(cblist, 1, NULL); #else return aio_suspend64(cblist, 1, NULL); #endif #else return aio_suspend(cblist, 1, NULL); #endif } /************************************************************************* * This routine is a generic async reader assist funtion. It takes * the same calling parameters as read() but also extends the * interface to include: * stride ..... For the async reads, what is the distance, in size units, * to space the reads. Note: Stride of 0 indicates that * you do not want any read-ahead. * max ..... What is the maximum file offset for this operation. * depth ..... How much read-ahead do you want. * * The calls to this will guarentee to complete the read() operation * before returning to the caller. The completion may occur in two * ways. First the operation may be completed by calling aio_read() * and then waiting for it to complete. Second the operation may be * completed by copying the data from a cache of previously completed * async operations. * In the event the read to be satisfied is not in the cache then a * series of async operations will be scheduled and then the first * async read will be completed. In the event that the read() can be * satisfied from the cache then the data is copied back to the * user buffer and a series of async reads will be initiated. If a * read is issued and the cache contains data and the read can not * be satisfied from the cache, then the cache is discarded, and * a new cache is constructed. * Note: All operations are aio_read(). The series will be issued * as asyncs in the order requested. After all are in flight * then the code will wait for the manditory first read. *************************************************************************/ #ifdef HAVE_ANSIC_C int async_read(struct cache *gc, long long fd, char *ubuffer, off64_t offset, long long size, long long stride, off64_t max, long long depth) #else int async_read(gc, fd, ubuffer, offset, size, stride, max, depth) struct cache *gc; long long fd; char *ubuffer; off64_t offset; long long size; long long stride; off64_t max; long long depth; #endif { off64_t a_offset,r_offset; long long a_size; struct cache_ent *ce,*first_ce=0; long long i; ssize_t retval=0; ssize_t ret; long long start = 0; long long del_read=0; a_offset=offset; a_size = size; /* * Check to see if it can be completed from the cache */ if((ce=(struct cache_ent *)incache(gc,fd,offset,size))) { while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) { async_suspend(ce); } if(ret) { printf("aio_error 1: ret %zd %d\n",ret,errno); } retval=aio_return(&ce->myaiocb); if(retval > 0) { mbcopy((char *)ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval); } if(retval < ce->myaiocb.aio_nbytes) { printf("aio_return error1: ret %zd %d\n",retval,errno); printf("aio_return error1: fd %d offset %lld buffer %p size %zd Opcode %d\n", ce->myaiocb.aio_fildes, (long long)ce->myaiocb.aio_offset, ce->myaiocb.aio_buf, ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode ); } ce->direct=0; takeoff_cache(gc,ce); }else { /* * Clear the cache and issue the first request async() */ del_cache(gc); del_read++; first_ce=alloc_cache(gc,fd,offset,size,(long long)LIO_READ); again: ret=aio_read(&first_ce->myaiocb); if(ret!=0) { if(errno==EAGAIN) goto again; else printf("error returned from aio_read(). Ret %zd errno %d\n",ret,errno); } } if(stride==0) /* User does not want read-ahead */ goto out; if(a_offset<0) /* Before beginning of file */ goto out; if(a_offset+size>max) /* After end of file */ goto out; if(depth >=(max_depth-1)) depth=max_depth-1; if(depth==0) goto out; if(gc->count > 1) start=depth-1; for(i=start;i max) continue; if((ce=incache(gc,fd,r_offset,a_size))) continue; ce=alloc_cache(gc,fd,r_offset,a_size,(long long)LIO_READ); ret=aio_read(&ce->myaiocb); if(ret!=0) { takeoff_cache(gc,ce); break; } } out: if(del_read) /* Wait for the first read to complete */ { while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) { async_suspend(first_ce); } if(ret) printf("aio_error 2: ret %zd %d\n",ret,errno); retval=aio_return(&first_ce->myaiocb); if(retval < first_ce->myaiocb.aio_nbytes) { printf("aio_return error2: ret %zd %d\n",retval,errno); printf("aio_return error2: fd %d offset %lld buffer %p size %zd Opcode %d\n", first_ce->myaiocb.aio_fildes, (long long)first_ce->myaiocb.aio_offset, first_ce->myaiocb.aio_buf, first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode ); } if(retval > 0) { mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval); } first_ce->direct=0; takeoff_cache(gc,first_ce); } return((int)retval); } /************************************************************************ * This routine allocates a cache_entry. It contains the * aiocb block as well as linkage for use in the cache mechanism. * The space allocated here will be released after the cache entry * has been consumed. The routine takeoff_cache() will be called * after the data has been copied to user buffer or when the * cache is purged. The routine takeoff_cache() will also release * all memory associated with this cache entry. ************************************************************************/ #ifdef HAVE_ANSIC_C struct cache_ent * alloc_cache(struct cache *gc,long long fd,off64_t offset,long long size,long long op) #else struct cache_ent * alloc_cache(gc,fd,offset,size,op) struct cache *gc; long long fd,size,op; off64_t offset; #endif { struct cache_ent *ce; intptr_t temp; ce=(struct cache_ent *)malloc((size_t)sizeof(struct cache_ent)); if(ce == (struct cache_ent *)0) { printf("Malloc failed\n"); exit(175); } bzero(ce,sizeof(struct cache_ent)); ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off64_t)offset; ce->real_address = malloc((size_t)(size+page_size)); printf("\nAllocate buffer2 %p Size %lld \n",ce->real_address,size+page_size); temp = (intptr_t)ce->real_address; temp = (temp+(page_size-1)) & ~(page_size-1); ce->myaiocb.aio_buf=(volatile void *)temp; if(ce->myaiocb.aio_buf == NULL) { printf("Malloc failed\n"); exit(176); } /*bzero(ce->myaiocb.aio_buf,(size_t)size);*/ ce->myaiocb.aio_reqprio=0; ce->myaiocb.aio_nbytes=(size_t)size; ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb.aio_lio_opcode=(int)op; ce->fd=(int)fd; ce->forward=0; ce->back=gc->tail; if(gc->tail) gc->tail->forward = ce; gc->tail= ce; if(!gc->head) gc->head=ce; gc->count++; return(ce); } /************************************************************************ * This routine checks to see if the requested data is in the * cache. *************************************************************************/ #ifdef HAVE_ANSIC_C struct cache_ent * incache(struct cache *gc, long long fd, off64_t offset, long long size) #else struct cache_ent * incache(gc,fd,offset,size) struct cache *gc; long long fd,size; off64_t offset; #endif { struct cache_ent *move; if(gc->head==0) { return(0); } move=gc->head; while(move) { if((move->fd == fd) && (move->myaiocb.aio_offset==(off64_t)offset) && ((size_t)size==move->myaiocb.aio_nbytes)) { return(move); } move=move->forward; } return(0); } /************************************************************************ * This routine removes a specific cache entry from the cache, and * releases all memory associated witht the cache entry (if not direct). *************************************************************************/ void takeoff_cache(struct cache *gc, struct cache_ent *ce) { struct cache_ent *move; long long found; move=gc->head; if(move==ce) /* Head of list */ { gc->head=ce->forward; if(gc->head) gc->head->back=0; else gc->tail = 0; if(!ce->direct) { if(ce->real_address != NULL) free((void *)(ce->real_address)); ce->real_address = NULL; if(ce != NULL) free((void *)ce); ce = NULL; } gc->count--; return; } found=0; while(move) { if(move==ce) { if(move->forward) { move->forward->back=move->back; } if(move->back) { move->back->forward=move->forward; } found=1; break; } else { move=move->forward; } } if(gc->head == ce) gc->tail = ce; if(!found) printf("Internal Error in takeoff cache\n"); move=gc->head; if(!ce->direct) { if(ce->real_address != NULL) free((void *)(ce->real_address)); ce->real_address = NULL; if(ce != NULL) free((void *)ce); ce = NULL; } gc->count--; } /************************************************************************ * This routine is used to purge the entire cache. This is called when * the cache contains data but the incomming read was not able to * be satisfied from the cache. This indicates that the previous * async read-ahead was not correct and a new pattern is emerging. ************************************************************************/ #ifdef HAVE_ANSIC_C void del_cache(struct cache *gc) #else void del_cache(gc) struct cache *gc; #endif { struct cache_ent *ce; ssize_t ret; ce=gc->head; while(1) { ce=gc->head; if(ce==0) return; while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED) ; ret = aio_return(&ce->myaiocb); ce->direct=0; takeoff_cache(gc,ce); /* remove from cache */ } } /************************************************************************ * Like its sister async_read() this function performs async I/O for * all buffers but it differs in that it expects the caller to * request a pointer to the data to be returned instead of handing * the function a location to put the data. This will allow the * async I/O to be performed and does not require any bcopy to be * done to put the data back into the location specified by the caller. ************************************************************************/ #ifdef HAVE_ANSIC_C int async_read_no_copy(struct cache *gc, long long fd, char **ubuffer, off64_t offset, long long size, long long stride, off64_t max, long long depth) #else int async_read_no_copy(gc, fd, ubuffer, offset, size, stride, max, depth) struct cache *gc; long long fd; char **ubuffer; off64_t offset; long long size; long long stride; off64_t max; long long depth; #endif { off64_t a_offset,r_offset; long long a_size; struct cache_ent *ce,*first_ce=0; long long i; ssize_t retval=0; ssize_t ret; long long del_read=0; long long start=0; a_offset=offset; a_size = size; /* * Check to see if it can be completed from the cache */ if((ce=(struct cache_ent *)incache(gc,fd,offset,size))) { while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) { async_suspend(ce); } if(ret) printf("aio_error 3: ret %zd %d\n",ret,errno); printf("It changed in flight\n"); retval=aio_return(&ce->myaiocb); if(retval > 0) { *ubuffer= (char *)ce->myaiocb.aio_buf; }else *ubuffer= NULL; if(retval < ce->myaiocb.aio_nbytes) { printf("aio_return error4: ret %zd %d\n",retval,errno); printf("aio_return error4: fd %d offset %lld buffer %p size %zd Opcode %d\n", ce->myaiocb.aio_fildes, (long long)ce->myaiocb.aio_offset, ce->myaiocb.aio_buf, ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode ); } ce->direct=1; takeoff_cache(gc,ce); /* do not delete buffer*/ putoninuse(gc,ce); }else { /* * Clear the cache and issue the first request async() */ del_cache(gc); del_read++; first_ce=alloc_cache(gc,fd,offset,size,(long long)LIO_READ); /* allocate buffer */ /*printf("allocated buffer/read %x offset %d\n",first_ce->myaiocb.aio_buf,offset);*/ again: first_ce->oldbuf=first_ce->myaiocb.aio_buf; first_ce->oldfd=first_ce->myaiocb.aio_fildes; first_ce->oldsize=first_ce->myaiocb.aio_nbytes; ret=aio_read(&first_ce->myaiocb); if(ret!=0) { if(errno==EAGAIN) goto again; else printf("error returned from aio_read(). Ret %zd errno %d\n",ret,errno); } } if(stride==0) /* User does not want read-ahead */ goto out; if(a_offset<0) /* Before beginning of file */ goto out; if(a_offset+size>max) /* After end of file */ goto out; if(depth >=(max_depth-1)) depth=max_depth-1; if(depth==0) goto out; if(gc->count > 1) start=depth-1; for(i=start;i max) continue; if((ce=incache(gc,fd,r_offset,a_size))) continue; ce=alloc_cache(gc,fd,r_offset,a_size,(long long)LIO_READ); ce->oldbuf=ce->myaiocb.aio_buf; ce->oldfd=ce->myaiocb.aio_fildes; ce->oldsize=ce->myaiocb.aio_nbytes; ret=aio_read(&ce->myaiocb); if(ret!=0) { takeoff_cache(gc,ce); break; } } out: if(del_read) /* Wait for the first read to complete */ { while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) { async_suspend(first_ce); } if(ret) printf("aio_error 4: ret %zd %d\n",ret,errno); if(first_ce->oldbuf != first_ce->myaiocb.aio_buf || first_ce->oldfd != first_ce->myaiocb.aio_fildes || first_ce->oldsize != first_ce->myaiocb.aio_nbytes) printf("It changed in flight2\n"); retval=aio_return(&first_ce->myaiocb); if(retval < first_ce->myaiocb.aio_nbytes) { printf("aio_return error5: ret %zd %d\n",retval,errno); printf("aio_return error5: fd %d offset %lld buffer %p size %zd Opcode %d\n", first_ce->myaiocb.aio_fildes, (long long)first_ce->myaiocb.aio_offset, first_ce->myaiocb.aio_buf, first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode ); } if(retval > 0) { *ubuffer= (char *)first_ce->myaiocb.aio_buf; }else *ubuffer= NULL; first_ce->direct=1; /* do not delete the buffer */ takeoff_cache(gc,first_ce); putoninuse(gc,first_ce); } return((int)retval); } /************************************************************************ * The caller is now finished with the data that was provided so * the library is now free to return the memory to the pool for later * reuse. ************************************************************************/ #ifdef HAVE_ANSIC_C void async_release(struct cache *gc) #else void async_release(gc) struct cache *gc; #endif { takeoffinuse(gc); } /************************************************************************ * Put the buffer on the inuse list. When the user is finished with * the buffer it will call back into async_release and the items on the * inuse list will be deallocated. ************************************************************************/ #ifdef HAVE_ANSIC_C void putoninuse(struct cache *gc,struct cache_ent *entry) #else void putoninuse(gc,entry) struct cache *gc; struct cache_ent *entry; #endif { if(gc->inuse_head) entry->forward=gc->inuse_head; else entry->forward=0; gc->inuse_head=entry; } /************************************************************************ * This is called when the application is finished with the data that * was provided. The memory may now be returned to the pool. ************************************************************************/ #ifdef HAVE_ANSIC_C void takeoffinuse(struct cache *gc) #else void takeoffinuse(gc) struct cache *gc; #endif { struct cache_ent *ce; if(gc->inuse_head==0) printf("Takeoffinuse error\n"); ce=gc->inuse_head; gc->inuse_head=gc->inuse_head->forward; if(gc->inuse_head !=0) printf("Error in take off inuse\n"); if(ce->real_address != NULL) free((void*)(ce->real_address)); ce->real_address = NULL; if(ce != NULL) free(ce); ce = NULL; } /************************************************************************* * This routine is a generic async writer assist funtion. It takes * the same calling parameters as write() but also extends the * interface to include: * * offset ..... offset in the file. * depth ..... How much read-ahead do you want. * *************************************************************************/ #ifdef HAVE_ANSIC_C size_t async_write(struct cache *gc,long long fd,char *buffer,long long size,off64_t offset,long long depth) #else size_t async_write(gc,fd,buffer,size,offset,depth) struct cache *gc; long long fd,size; char *buffer; off64_t offset; long long depth; #endif { struct cache_ent *ce; size_t ret; ce=allocate_write_buffer(gc,fd,offset,size,(long long)LIO_WRITE,depth,0LL,(char *)0,(char *)0); ce->direct=0; /* not direct. Lib supplies buffer and must free it */ mbcopy(buffer,(char *)(ce->myaiocb.aio_buf),(size_t)size); async_put_on_write_queue(gc,ce); /* printf("asw: fd %d offset %lld, size %zd\n",ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); */ again: ret=aio_write(&ce->myaiocb); if(ret==-1) { if(errno==EAGAIN) { async_wait_for_write(gc); goto again; } if(errno==0) { /* Compensate for bug in async library */ async_wait_for_write(gc); goto again; } else { printf("Error in aio_write: ret %zd errno %d count %lld\n",ret,errno,gc->w_count); /* printf("aio_write_no_copy: fd %d buffer %x offset %lld size %zd\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_buf, ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); */ exit(177); } } return((ssize_t)size); } /************************************************************************* * Allocate a write aiocb and write buffer of the size specified. Also * put some extra buffer padding so that VX_DIRECT can do its job when * needed. *************************************************************************/ #ifdef HAVE_ANSIC_C struct cache_ent * allocate_write_buffer( struct cache *gc, long long fd, long long offset, long long size,long long op, long long w_depth, long long direct, char *buffer, char *free_addr) #else struct cache_ent * allocate_write_buffer(gc,fd,offset,size,op,w_depth,direct,buffer,free_addr) struct cache *gc; long long fd,size,op; off64_t offset; long long w_depth; long long direct; char *buffer,*free_addr; #endif { struct cache_ent *ce; intptr_t temp; if(fd==0LL) { printf("Setting up write buffer insane\n"); exit(178); } if(gc->w_count > w_depth) async_wait_for_write(gc); ce=(struct cache_ent *)malloc((size_t)sizeof(struct cache_ent)); if(ce == (struct cache_ent *)0) { printf("Malloc failed 1\n"); exit(179); } bzero(ce,sizeof(struct cache_ent)); ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off_t)offset; if(!direct) { ce->real_address = malloc((size_t)(size+page_size)); temp = (intptr_t)ce->real_address; temp = (temp+(page_size-1)) & ~(page_size-1); ce->myaiocb.aio_buf=(volatile void *)temp; } else { ce->myaiocb.aio_buf=(volatile void *)buffer; ce->real_address=(char *)free_addr; } if(ce->myaiocb.aio_buf == 0) { printf("Malloc failed 2\n"); exit(180); } ce->myaiocb.aio_reqprio=0; ce->myaiocb.aio_nbytes=(size_t)size; ce->myaiocb.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb.aio_lio_opcode=(int)op; ce->fd=(int)fd; return(ce); } /************************************************************************* * Put it on the outbound queue. *************************************************************************/ #ifdef HAVE_ANSIC_C void async_put_on_write_queue(struct cache *gc,struct cache_ent *ce) #else void async_put_on_write_queue(gc,ce) struct cache *gc; struct cache_ent *ce; #endif { ce->forward=0; ce->back=gc->w_tail; if(gc->w_tail) gc->w_tail->forward = ce; gc->w_tail= ce; if(!gc->w_head) gc->w_head=ce; gc->w_count++; return; } /************************************************************************* * Cleanup all outstanding writes *************************************************************************/ #ifdef HAVE_AHSIC_C void async_write_finish(struct cache *gc) #else void async_write_finish(gc) struct cache *gc; #endif { while(gc->w_head) { async_wait_for_write(gc); } } /************************************************************************* * Wait for an I/O to finish *************************************************************************/ #ifdef HAVE_ANSIC_C void async_wait_for_write(struct cache *gc) #else void async_wait_for_write(gc) struct cache *gc; #endif { struct cache_ent *ce; size_t ret; int retval; if(gc->w_head==0) return; ce=gc->w_head; if(ce == NULL) return; gc->w_head=ce->forward; gc->w_count--; ce->forward=NULL; if(ce==gc->w_tail) gc->w_tail=0; /*printf("Wait for buffer %x offset %lld size %zd to finish\n", ce->myaiocb.aio_buf, ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); printf("write count %lld \n",gc->w_count); */ while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) { async_suspend(ce); } if(ret) { printf("aio_error 5: ret %zd %d\n",ret,errno); printf("fd %d offset %lld size %zd\n", ce->myaiocb.aio_fildes, (long long)ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); exit(181); } retval=aio_return(&ce->myaiocb); if(retval < 0) { printf("aio_return error: %d\n",errno); } if(!ce->direct) { if(ce->real_address != NULL) free((void *)(ce->real_address)); /* Causes crash. */ ce->real_address=NULL; if(ce != NULL) free((void *)ce); ce=NULL; } } /************************************************************************* * This routine is a generic async writer assist funtion. It takes * the same calling parameters as write() but also extends the * interface to include: * * offset ..... offset in the file. * depth ..... How much read-ahead do you want. * free_addr .. address of memory to free after write is completed. * *************************************************************************/ #ifdef HAVE_ANSIC_C size_t async_write_no_copy(struct cache *gc,long long fd,char *buffer,long long size,long long offset,long long depth,char *free_addr) #else size_t async_write_no_copy(gc,fd,buffer,size,offset,depth,free_addr) struct cache *gc; long long fd,size; char *buffer; long long offset; long long depth; char *free_addr; #endif { struct cache_ent *ce; size_t ret; long long direct = 1; ce=allocate_write_buffer(gc,fd,offset,size,(long long)LIO_WRITE,depth,direct,buffer,free_addr); ce->direct=0; /* have library de-allocate the buffer */ async_put_on_write_queue(gc,ce); /* printf("awnc: fd %d offset %lld, size %zd\n",ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); */ again: ret=aio_write(&ce->myaiocb); if(ret==-1) { if(errno==EAGAIN) { async_wait_for_write(gc); goto again; } if(errno==0) { /* Compensate for bug in async library */ async_wait_for_write(gc); goto again; } else { printf("Error in aio_write: ret %zd errno %d\n",ret,errno); printf("aio_write_no_copy: fd %d buffer %p offset %lld size %zd\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_buf, (long long)ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); exit(182); } } else { return((ssize_t)size); } } void mbcopy(source, dest, len) const char *source; char *dest; size_t len; { int i; for(i=0;i #endif #include #include #include #if defined(__AIX__) || defined(__FreeBSD__) || defined(__DragonFly__) #include #else #include #endif #if defined(OSV5) || defined(linux) || defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__NetBSD__) #include #endif #if defined(linux) || defined(__DragonFly__) || defined(IOZ_macosx) || defined(__NetBSD__) || defined(Windows) #include #include #endif #if (defined(solaris) && defined( __LP64__ )) || defined(__s390x__) || defined(__FreeBSD__) /* If we are building for 64-bit Solaris, all functions that return pointers * must be declared before they are used; otherwise the compiler will assume * that they return ints and the top 32 bits of the pointer will be lost, * causing segmentation faults. The following includes take care of this. * It should be safe to add these for all other OSs too, but we're only * doing it for Solaris now in case another OS turns out to be a special case. */ #include #include #include #include #include #endif /* Little Endian */ #define ENDIAN_1 1 /* Big Endian */ #define ENDIAN_2 2 /* Middle Endian */ #define ENDIAN_3 3 /* Middle Endian */ #define ENDIAN_4 4 int junk, *junkp; #ifdef HAVE_ANSIC_C /************************************************************************/ /* Here is the API... Enjoy */ /************************************************************************/ /* Create worksheet */ int create_xls(char *); /* Args: Filename */ /* */ /* Close worksheet */ void close_xls(int); /* Args: file descriptor */ /* */ /* Put a 16 bit integer in worksheet */ void do_int(int,int,int,int); /* Args: file descriptor, */ /* value, */ /* row, */ /* column */ /* Put a double in 8 byte float */ void do_float(int,double,int,int); /* Args: file descriptor, */ /* value, */ /* row, */ /* column */ /* Put a string in worksheet */ void do_label(int,char *,int,int); /* Args: file descriptor, */ /* string, */ /* row, */ /* column */ /************************************************************************/ char libbif_version[] = "Libbif Version $Revision: 3.31 $"; #endif #define BOF 0x9 #define INTEGER 0x2 #define FLOAT 0x3 #define LABEL 0x4 #define EXCEL_VERS 0x2 #define WORKSHEET 0x10 struct bof_record{ /* Beginning of file */ char hi_opcode; char lo_opcode; char hi_length; char lo_length; char hi_version; /* Excel version */ char lo_version; char hi_filetype; char lo_filetype; }; struct int_record { char hi_opcode; /* Type 2 of record */ char lo_opcode; char hi_length; char lo_length; char hi_row; char lo_row; char hi_column; char lo_column; char rgbhi; char rgbmed; char rgblo; char hi_data; char lo_data; }; struct label_record { char hi_opcode; /* Type 4 of record */ char lo_opcode; char hi_length; char lo_length; char hi_row; char lo_row; char hi_column; char lo_column; char rgbhi; char rgbmed; char rgblo; char string_length; char str_array[256]; }; struct float_record { /* Type 3 record */ char hi_opcode; char lo_opcode; char hi_length; char lo_length; char hi_row; char lo_row; char hi_column; char lo_column; char rgbhi; char rgbmed; char rgblo; double data; }; #ifdef HAVE_ANSIC_C void close_xls(int); int create_xls(char *); void do_header(int); void do_int(int, int, int, int); void do_float(int, double, int, int); void do_label(int, char *, int, int ); void do_eof(int) ; int endian(void); #else void close_xls(); int create_xls(); void do_header(); void do_int(); void do_float(); void do_label(); void do_eof(); int endian(); #endif /* * Write the EOF and close the file */ #ifdef HAVE_ANSIC_C void close_xls(int fd) { #else void close_xls(fd) int fd; { #endif do_eof(fd); close(fd); } /* * Create xls worksheet. Create file and put the BOF record in it. */ #ifdef HAVE_ANSIC_C int create_xls(char *name) { #else create_xls(name) char *name; { #endif int fd; unlink(name); #ifdef Windows fd=open(name,O_BINARY|O_CREAT|O_RDWR,0666); #else fd=open(name,O_CREAT|O_RDWR,0666); #endif if(fd<0) { printf("Error opening file %s\n",name); exit(-1); } do_header(fd); return(fd); } #ifdef HAVE_ANSIC_C void do_header(int fd) /* Stick the BOF at the beginning of the file */ { #else do_header(fd) int fd; { #endif struct bof_record bof; bof.hi_opcode=BOF; bof.lo_opcode = 0x0; bof.hi_length=0x4; bof.lo_length=0x0; bof.hi_version=EXCEL_VERS; bof.lo_version=0x0; bof.hi_filetype=WORKSHEET; bof.lo_filetype=0x0; junk=write(fd,&bof,sizeof(struct bof_record)); } /* * Put an integer (16 bit) in the worksheet */ #ifdef HAVE_ANSIC_C void do_int(int fd,int val, int row, int column) { #else do_int(fd,val,row,column) int fd,val,row,column; { #endif struct int_record intrec; short s_row,s_column; s_row=(short)row; s_column=(short)column; intrec.hi_opcode=INTEGER; intrec.lo_opcode=0x00; intrec.hi_length=0x09; intrec.lo_length=0x00; intrec.rgbhi=0x0; intrec.rgbmed=0x0; intrec.rgblo=0x0; intrec.hi_row=(char)s_row&0xff; intrec.lo_row=(char)(s_row>>8)&0xff; intrec.hi_column=(char)(s_column&0xff); intrec.lo_column=(char)(s_column>>8)&0xff; intrec.hi_data=(val & 0xff); intrec.lo_data=(val & 0xff00)>>8; junk=write(fd,&intrec,13); } /* Note: This routine converts Big Endian to Little Endian * and writes the record out. */ /* * Put a double in the worksheet as 8 byte float in IEEE format. */ #ifdef HAVE_ANSIC_C void do_float(int fd, double value, int row, int column) { #else do_float(fd, value, row, column) int fd; double value; int row,column; { #endif struct float_record floatrec; short s_row,s_column; unsigned char *sptr,*dptr; s_row=(short)row; s_column=(short)column; floatrec.hi_opcode=FLOAT; floatrec.lo_opcode=0x00; floatrec.hi_length=0xf; floatrec.lo_length=0x00; floatrec.rgbhi=0x0; floatrec.rgbmed=0x0; floatrec.rgblo=0x0; floatrec.hi_row=(char)(s_row&0xff); floatrec.lo_row=(char)((s_row>>8)&0xff); floatrec.hi_column=(char)(s_column&0xff); floatrec.lo_column=(char)((s_column>>8)&0xff); sptr =(unsigned char *) &value; dptr =(unsigned char *) &floatrec.data; if(endian()==ENDIAN_2) /* Big Endian */ { dptr[0]=sptr[7]; /* Convert to Little Endian */ dptr[1]=sptr[6]; dptr[2]=sptr[5]; dptr[3]=sptr[4]; dptr[4]=sptr[3]; dptr[5]=sptr[2]; dptr[6]=sptr[1]; dptr[7]=sptr[0]; } if(endian()==ENDIAN_3) /* Middle Endian */ { dptr[0]=sptr[4]; /* 16 bit swapped ARM */ dptr[1]=sptr[5]; dptr[2]=sptr[6]; dptr[3]=sptr[7]; dptr[4]=sptr[0]; dptr[5]=sptr[1]; dptr[6]=sptr[2]; dptr[7]=sptr[3]; } if(endian()==ENDIAN_1) /* Little Endian */ { dptr[0]=sptr[0]; /* Do not convert to Little Endian */ dptr[1]=sptr[1]; dptr[2]=sptr[2]; dptr[3]=sptr[3]; dptr[4]=sptr[4]; dptr[5]=sptr[5]; dptr[6]=sptr[6]; dptr[7]=sptr[7]; } if(endian()==-1) /* Unsupported architecture */ { dptr[0]=0; dptr[1]=0; dptr[2]=0; dptr[3]=0; dptr[4]=0; dptr[5]=0; dptr[6]=0; dptr[7]=0; printf("Excel output not supported on this architecture.\n"); } junk=write(fd,&floatrec,11); /* Don't write floatrec. Padding problems */ junk=write(fd,&floatrec.data,8); /* Write value seperately */ } /* * Put a string as a label in the worksheet. */ #ifdef HAVE_ANSIC_C void do_label(int fd, char *string, int row, int column) { #else do_label(fd, string, row, column) int fd; char *string; int row,column; { #endif struct label_record labelrec; short s_row,s_column; int i; for(i=0;i<255;i++) labelrec.str_array[i]=0; s_row=(short)row; s_column=(short)column; i=strlen(string); labelrec.hi_opcode=LABEL; labelrec.lo_opcode=0x00; labelrec.hi_length=0x08; /* 264 total bytes */ labelrec.lo_length=0x01; labelrec.rgblo=0x0; labelrec.rgbmed=0x0; labelrec.rgbhi=0x0; labelrec.hi_row=(char)(s_row&0xff); labelrec.lo_row=(char)((s_row>>8)&0xff); labelrec.hi_column=(char)(s_column&0xff); labelrec.lo_column=(char)((s_column>>8)&0xff); labelrec.string_length=i; if(i > 255) /* If too long then terminate it early */ string[254]=0; i=strlen(string); strcpy(labelrec.str_array,string); junk=write(fd,&labelrec,sizeof(struct label_record)); } /* * Write the EOF in the file */ #ifdef HAVE_ANSIC_C void do_eof(int fd) { #else do_eof(fd) int fd; { #endif char buf[]={0x0a,0x00,0x00,0x00}; junk=write(fd,buf,4); } /* * Routine to determine the Endian-ness of the system. This * is needed for Iozone to convert doubles (floats) into * Little-endian format. This is needed for Excel to be * able to interpret the file */ int endian(void) { long long foo = 0x0102030405060708LL; long foo1 = 0x012345678; unsigned char *c,c1,c2,c3,c4,c5,c6,c7,c8; c=(unsigned char *)&foo; c1=*c++; c2=*c++; c3=*c++; c4=*c++; c5=*c++; c6=*c++; c7=*c++; c8=*c; /*--------------------------------------------------------------*/ /* printf("%x %x %x %x %x %x %x %x\n",c1,c2,c3,c4,c5,c6,c7,c8); */ /*--------------------------------------------------------------*/ /* Little Endian format ? ( Intel ) */ if( (c1==0x08) && (c2==0x07) && (c3==0x06) && (c4==0x05) && (c5==0x04) && (c6==0x03) && (c7==0x02) && (c8==0x01) ) return(ENDIAN_1); /* Big Endian format ? ( Sparc, Risc... */ if( (c1==0x01) && (c2==0x02) && (c3==0x03) && (c4==0x04) && (c5==0x05) && (c6==0x06) && (c7==0x07) && (c8==0x08) ) return(ENDIAN_2); /* Middle Endian format ? ( ARM ... ) */ if( (c1==0x04) && (c2==0x03) && (c3==0x02) && (c4==0x01) && (c5==0x08) && (c6==0x07) && (c7==0x06) && (c8==0x05) ) return(ENDIAN_3); c=(unsigned char *)&foo1; c1=*c++; c2=*c++; c3=*c++; c4=*c++; /* Another middle endian format ? ( PDP-11 ... ) */ if( (c1==0x34) && (c2==0x12) && (c3==0x78) && (c4==0x56)) return(ENDIAN_4); return(-1); } iozone3_488/src/current/gnuplot.dem0000444000175000017500000000313413573734166016513 0ustar cappscapps# # $Id: Plot of latency versus offset in a file # # Requires data file "wol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system write latency " set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'wol.dat' using 1:2 title "Latency Plot" with lines pause -1 "Hit return to continue" # # $Id: Plot of latency versus offset in a file # # Requires data file "rwol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system re-write latency " set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'rwol.dat' using 1:2 title "Latency Plot" with lines pause -1 "Hit return to continue" # # $Id: Plot of latency versus offset in a file # # Requires data file "rol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system read latency " set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'rol.dat' using 1:2 title "Latency Plot" with lines pause -1 "Hit return to continue" # # $Id: Plot of latency versus offset in a file # # Requires data file "rrol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system re-read latency " set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'rrol.dat' using 1:2 title "Latency Plot" with lines pause -1 "Hit return to continue" iozone3_488/src/current/gengnuplot.sh0000551000175000017500000000522313573734166017052 0ustar cappscapps#!/bin/sh # # Copyright (c) 2001 Yves Rougy Yves@Rougy.net # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA cp $1 iozone_gen_out file_name=iozone_gen_out #set -x write_gnuplot_file() { echo \#test : $query case $query in (write) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $3 }' < $file_name ;; (rewrite) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $4 }' < $file_name ;; (read) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $5 }' < $file_name ;; (reread) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $6 }' < $file_name ;; (randread) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $7 }' < $file_name ;; (randwrite) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $8 }' < $file_name ;; (bkwdread) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $9 }' < $file_name ;; (recrewrite) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $10 }' < $file_name ;; (strideread) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $11 }' < $file_name ;; (fwrite) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $12 }' < $file_name ;; (frewrite) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $13 }' < $file_name ;; (fread) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $14 }' < $file_name ;; (freread) awk '$1 ~ /^[0-9]+/ { print $1 " " $2 " " $15 }' < $file_name ;; (*) echo "Usage : gengnuplot.sh " >> /dev/stderr ; echo "filename is the output of iozone -a" >> /dev/stderr ; echo "test is one of write rewrite read reread randread randwrite bkwdread recrewrite strideread fwrite frewrite fread freread" >> /dev/stderr ;; esac } #filename=$1 filename=iozone_gen_out query=$2 if (! [ -e $query ] ) ; then mkdir $query; fi if ( [ $# -eq 2 ] ) ; then write_gnuplot_file > $query/`basename $file_name.gnuplot` else echo "Usage : gengnuplot.sh " 2>&1 echo "filename is the output of iozone -a" 2>&1 echo "test is one of write rewrite read reread randread randwrite bkwdread recrewrite strideread fwrite frewrite fread freread" 2>&1 fi iozone3_488/src/current/Generate_Graphs0000551000175000017500000000137713573734166017323 0ustar cappscapps# # This script will create the Iozone graphs using # gnuplot. # # # # ------------------------------------------------ # YOU MUST PROVIDE A FILE NAME FOR IT TO PROCESS. # This filename is the name of the file where you # sent Iozone's output. # ------------------------------------------------ # Generate data base for all of the operation types. ./gengnuplot.sh $1 write ./gengnuplot.sh $1 rewrite ./gengnuplot.sh $1 read ./gengnuplot.sh $1 reread ./gengnuplot.sh $1 randread ./gengnuplot.sh $1 randwrite ./gengnuplot.sh $1 bkwdread ./gengnuplot.sh $1 recrewrite ./gengnuplot.sh $1 strideread ./gengnuplot.sh $1 fwrite ./gengnuplot.sh $1 frewrite ./gengnuplot.sh $1 fread ./gengnuplot.sh $1 freread # Produce graphs and postscript results. gnuplot gnu3d.dem iozone3_488/src/current/iozone_visualizer.pl0000544000175000017500000002074713573734166020463 0ustar cappscapps#!/usr/bin/env perl use warnings; use strict; # arguments: one of more report files # # Christian Mautner , 2005-10-31 # Marc Schoechlin , 2007-12-02 # Pr Karlsson , 2012-07-24 # # This script is just a hack :-) # # This script is based loosely on the Generate_Graph set # of scripts that come with iozone, but is a complete re-write # # The main reason to write this was the need to compare the behaviour of # two or more different setups, for tuning filesystems or # comparing different pieces of hardware. # # This has been updated (2012) to take the new gnuplot 4 syntax into account, # and some general perl cleanups, despite its "hack" status. # It also requires some perl libraries to funktion, specifically # Readonly and List::MoreUtils which are not included in the standard # perl in most distributions. # # This script is in the public domain, too short and too trivial # to deserve a copyright. # # Simply run iozone like, for example, ./iozone -a -g 4G > config1.out (if your machine has 4GB) # # and then run perl report.pl config1.out # or get another report from another box into config2.out and run # perl report.pl config1.out config2.out # the look in the report_* directory for .png # # If you don't like png or the graphic size, search for "set terminal" in this file and put whatever gnuplot # terminal you want. Note I've also noticed that gnuplot switched the set terminal png syntax # a while back, you might need "set terminal png small size 900,700" use Carp; use English qw(-no_match_vars); use Getopt::Long; use List::MoreUtils qw(any); use Readonly; Readonly my $EMPTY => q{}; Readonly my $SPACE => q{ }; my $column; my %columns; my $datafile; my @datafiles; my $outdir; my $report; my $nooffset = 0; my @reports; my @split; my $size3d; my $size2d; # evaluate options GetOptions( '3d=s' => \$size3d, '2d=s' => \$size2d, 'nooffset' => \$nooffset ); if ( not defined $size3d ) { $size3d = '1280,960'; } if ( not defined $size2d ) { $size2d = '1024,768'; } my $xoffset = 'offset -7'; my $yoffset = 'offset -3'; if ( $nooffset == 1 ) { $xoffset = $EMPTY; $yoffset = $EMPTY; } print <<"_TEXT_"; iozone_visualizer.pl : this script is distributed as public domain Christian Mautner , 2005-10-31 Marc Schoechlin , 2007-12-02 Pr Karlsson , 2012-07-24 _TEXT_ @reports = @ARGV; if ( not @reports or any { m/^-/msx } @reports ) { print "usage: $PROGRAM_NAME --3d=x,y -2d=x,y [...]"; exit; } if ( any { m{/}msx } @reports ) { croak 'report files must be in current directory'; } print "Configured xtics-offset '$xoffset', configured ytics-offset '$yoffset' (disable with --nooffset)\n"; print 'Size 3d graphs : ' . $size3d . " (modify with '--3d=x,y')\n"; print 'Size 2d graphs : ' . $size2d . " (modify with '--2d=x,y')\n"; #KB reclen write rewrite read reread read write read rewrite read fwrite frewrite fread freread %columns = ( 'KB' => 1, 'reclen' => 2, 'write' => 3, 'rewrite' => 4, 'read' => 5, 'reread' => 6, 'randread' => 7, 'randwrite' => 8, 'bkwdread' => 9, 'recrewrite' => 10, 'strideread' => 11, 'fwrite' => 12, 'frewrite' => 13, 'fread' => 14, 'freread' => 15, ); # # create output directory. the name is the concatenation # of all report file names (minus the file extension, plus # prefix report_) # $outdir = 'report_' . join q{_}, map { m/([^.]+)([.].*)?/msx && $1 } (@reports); print {*STDERR} "Output directory: $outdir "; if ( -d $outdir ) { print {*STDERR} '(removing old directory) '; system "rm -rf $outdir"; } mkdir $outdir or croak "cannot make directory $outdir"; print {*STDERR} "done.\nPreparing data files..."; for my $report (@reports) { open my $fhr, '<', $report or croak "cannot open $report for reading"; $report =~ m/^([^\.]+)/msx; $datafile = "$1.dat"; push @datafiles, $datafile; open my $fho3, '>', "$outdir/$datafile" or croak "cannot open $outdir/$datafile for writing"; open my $fho2, '>', "$outdir/2d-$datafile" or croak "cannot open $outdir/$datafile for writing"; my @sorted = sort { $columns{$a} <=> $columns{$b} } keys %columns; print {$fho3} '# ' . join ($SPACE, @sorted) . "\n"; print {$fho2} '# ' . join ($SPACE, @sorted) . "\n"; my $old_x = 0; while (<$fhr>) { my $line = $_; if ( not $line =~ m/^[\s\d]+$/msx ) { next; } @split = split(); if ( @split != 15 ) { next; } if ( $old_x != $split[0] ) { print {$fho3} "\n"; } $old_x = $split[0]; print {$fho3} $line; if ( $split[1] == 16384 or $split[0] == $split[1] ) { print {$fho2} $line; } } close $fhr or carp $ERRNO; close $fho3 or carp $ERRNO; close $fho2 or carp $ERRNO; } print {*STDERR} "done.\nGenerating graphs:"; open my $fhtml, '>', "$outdir/index.html" or carp "cannot open $outdir/index.html for writing"; print {$fhtml} <<'_HTML_'; IOZone Statistics

IOZone Statistics

\n"; # Generate 3D plots for my $column ( keys %columns ) { if ( $column =~ m/KB|reclen/msx ) { next; } print {*STDERR} " $column"; open my $fhg, '>', "$outdir/$column.do" or croak "cannot open $outdir/$column.do for writing"; print {$fhg} <<"_GNUPLOT_"; set title "Iozone performance: $column" set grid lt 2 lw 1 set surface set xtics $xoffset set ytics $yoffset set logscale x 2 set logscale y 2 set autoscale z set xlabel "File size in Kbytes" set ylabel "Record size in Kbytes" set zlabel "Kb/s" set style data lines set dgrid3d 80,80,3 set terminal png small size $size3d nocrop set output "$column.png" _GNUPLOT_ # original term above: print {$fhtml} <<"_HTML_"; _HTML_ print {$fhg} 'splot ' . join q{, }, map { qq{"$_" using 1:2:$columns{$column} title "$_"} } @datafiles; print {$fhg} "\n"; close $fhg or carp $ERRNO; open $fhg, '>', "$outdir/2d-$column.do" or croak "cannot open $outdir/$column.do for writing"; print {$fhg} <<"_GNUPLOT_"; set title "Iozone performance: $column" #set terminal png small picsize 450 350 set terminal png medium size $size2d nocrop set logscale x set xlabel "File size in Kbytes" set ylabel "Kbytes/sec" set output "2d-$column.png" _GNUPLOT_ print {$fhtml} <<"_HTML_"; _HTML_ print {$fhg} 'plot ' . join q{, }, map { qq{"2d-$_" using 1:$columns{$column} title "$_" with lines} } (@datafiles); print {$fhg} "\n"; close $fhg or carp $ERRNO; if ( system "cd $outdir && gnuplot $column.do && gnuplot 2d-$column.do" ) { print {*STDERR} '(failed) '; } else { print {*STDERR} '(ok) '; } } print {$fhtml} <<'_HTML_';
_HTML_ # Generate Menu print {$fhtml} <<'_HTML_'; ## Overview
    _HTML_ for my $column ( keys %columns ) { if ( $column =~ m/KB|reclen/msx ) { next; } print {$fhtml} '
  • ' . uc($column) . ' : ' . '3d\n" . '2d
  • \n"; } print {$fhtml} "

3d-$column

[top]
3d-$column

2d-$column

[top]
2d-$column
_HTML_ print {*STDERR} "done.\n"; iozone3_488/src/current/gnu3d.dem0000551000175000017500000000531213573734166016042 0ustar cappscapps# # $Id: 3D plot of performance # # Processes files that were created by Generate_Graphs # and displays the results. Also, saves a postscript copy. # # Don Capps dirs = "write rewrite read reread randread randwrite bkwdread recrewrite strideread fwrite frewrite fread freread" titles = "Write ReWrite Read Reread Random_read Random_write Read_Backwards Record_rewrite Stride_read Fwrite Frewrite Fread Freread" file(n) = sprintf("%s/iozone_gen_out.gnuplot", word(dirs,n)) outfile(n) = sprintf("%s/%s.ps", word(dirs,n), word(dirs,n)) title(n) = word(titles,n) set title "Iozone performance" set grid lt 2 lw 1 set surface set parametric set xtics set ytics set logscale x 2 set logscale y 2 set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set style data lines set dgrid3d 80,80,3 i = 1 set terminal x11 set output splot file(i) title title(i) pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 2 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 3 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 4 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 5 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 6 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 7 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 8 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 9 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 10 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 11 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 12 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot i = 13 set terminal x11 set output replot pause -1 "Hit return to continue" set terminal postscript color set output outfile(i) replot iozone3_488/src/current/Gnuplot.txt0000551000175000017500000000135413573734166016526 0ustar cappscappsThe script Generate_Graphs will create the 3D surface plots and display them. It will also produce postscript outputs for each test and leave them in their respective sub-directory. It processes the output from an Iozone run. The output from Iozone that it is expecting is the text output from the iozone default behavior. (iozone -a, or iozone -az) How to produce graphs: Generate_Graphs iozone.out The gen_graphs script will: 1. Create the databases for each type of operation and then processes them with Gnuplot. 2. It will display each result on the X11 screen, and also save a copy in postscript in the test sub-directory. Thanks to Yves Rougy for providing the nifty scripts to help with the plots. iozone3_488/src/current/gnuplotps.dem0000444000175000017500000000322513573734166017057 0ustar cappscapps# # $Id: Plot of latency versus offset in a file # # Requires data file "wol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system write latency " set terminal postscript set output "gnu_wol.ps" set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'wol.dat' using 1:2 title "Latency Plot" with lines # # $Id: Plot of latency versus offset in a file # # Requires data file "rwol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system re-write latency " set terminal postscript set output "gnu_rwol.ps" set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'rwol.dat' using 1:2 title "Latency Plot" with lines # # $Id: Plot of latency versus offset in a file # # Requires data file "rol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system read latency " set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" set terminal postscript set output "gnu_rol.ps" plot 'rol.dat' using 1:2 title "Latency Plot" with lines # # $Id: Plot of latency versus offset in a file # # Requires data file "rrol.dat" from this directory, # so change current working directory to this directory before running. # set title "File system re-read latency " set terminal postscript set output "gnu_rrol.ps" set autoscale x set xtics set xlabel "Offset in file (KB)" set ylabel "Latency in Microseconds" plot 'rrol.dat' using 1:2 title "Latency Plot" with lines iozone3_488/src/current/read_telemetry0000444000175000017500000000112213573734166017257 0ustar cappscapps# # # The format is: # # All fields are space delimited. # A # symbol in column 1 indicates a comment. # First field: Byte offset within the file. # Second field: Size in bytes of the I/O operation. # Third field: Number of milliseconds to delay before I/O operation. # # This is an example of sequential 64k reader with 2 milliseconds # before each read. # 0 65536 2 65536 65536 2 131072 65536 2 196608 65536 2 262144 65536 2 327680 65536 2 393216 65536 2 458752 65536 2 524288 65536 2 589824 65536 2 655360 65536 2 720896 65536 2 786432 65536 2 851968 65536 2 917504 65536 2 983040 65536 2 iozone3_488/src/current/write_telemetry0000444000175000017500000000112313573734166017477 0ustar cappscapps# # # The format is: # # All fields are space delimited. # A # symbol in column 1 indicates a comment. # First field: Byte offset within the file. # Second field: Size in bytes of the I/O operation. # Third field: Number of milliseconds to delay before I/O operation. # # This is an example of sequential 64k writer with 2 milliseconds # before each write. # 0 65536 2 65536 65536 2 131072 65536 2 196608 65536 2 262144 65536 2 327680 65536 2 393216 65536 2 458752 65536 2 524288 65536 2 589824 65536 2 655360 65536 2 720896 65536 2 786432 65536 2 851968 65536 2 917504 65536 2 983040 65536 2 iozone3_488/src/current/client_list0000444000175000017500000000243313573734166016571 0ustar cappscapps# # Lines that start with # in column 0 are comments. # # There are now two formats supported. # Format: 3 fields, space delimited. # Format: 4 fields, space delimited. # # Format: 3 fields, space delimited. # client_name working_dir_on_client path_to_iozone_on_client # Format: 4 fields, space delimited. # client_name working_dir_on_client path_to_iozone_on_client path_to_testfile # # Example: With two clients (format 3 fields) # # client1 /home/user/tmp /home/user/tmp/iozone # client2 /home/user/tmp /home/user/tmp/iozone # # # Example: With two copies of Iozone on each of the two clients # (format 3 fields) # # client1 /home/user/tmp /home/user/tmp/iozone # client1 /home/user/tmp /home/user/tmp/iozone # client2 /home/user/tmp /home/user/tmp/iozone # client2 /home/user/tmp /home/user/tmp/iozone # # Example: With two clients (format 4 fields) # client1 /home/user/tmp /home/user/tmp/iozone /tmp/foo1 # client2 /home/user/tmp /home/user/tmp/iozone /tmp/foo2 # # Example: With two copies of Iozone on each of the two clients # (format 4 fields) # client1 /home/user/tmp /home/user/tmp/iozone /tmp/foo1 # client1 /home/user/tmp /home/user/tmp/iozone /tmp/foo2 # client2 /home/user/tmp /home/user/tmp/iozone /tmp/foo3 # client2 /home/user/tmp /home/user/tmp/iozone /tmp/foo4 iozone3_488/src/current/spec.in0000444000175000017500000000556513573734166015630 0ustar cappscappsSummary: Iozone Filesystem Benchmark Name: iozone Version: 3 Release: 488 License: Freeware Group: Applications/Engineering Source: %{name}%{version}_%{release}.tar Buildroot: /var/tmp/%{name}-buildroot %description IOzone is a filesystem benchmark tool. The benchmark generates and measures a variety of file operations. Iozone has been ported to many machines and runs under many operating systems. Iozone is useful for performing a broad filesystem analysis of a vendors computer platform. The benchmark tests file I/O performance for the following operations: Read, write, re-read, re-write, read backwards, read strided, fread, fwrite, random read, pread ,mmap, aio_read, aio_write. ## ## PREP ## %prep ## ## SETUP and PATCH ## %setup -n iozone3_488/src/current ## ## BUILD ## ## ## BUILD ## %build %ifarch %{ix86} make linux %else %ifarch x86_64 make linux-AMD64 %else %ifarch ia64 make linux-ia64 %else %ifarch ppc make linux-powerpc %else %ifarch ppc64 make linux-powerpc64 %else %ifarch s390 make linux-S390 %else %ifarch s390x make linux-S390X %else %ifarch %(arm) make linux-arm %else echo "No idea how to build for your arch..." exit 1 %endif %endif %endif %endif %endif %endif %endif %endif ## ## INSTALL ## %install mkdir -p $RPM_BUILD_ROOT/opt/iozone/bin cp $RPM_BUILD_DIR/iozone3_488/src/current/iozone $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_488/src/current/fileop $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_488/src/current/pit_server $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_488/src/current/Generate_Graphs $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_488/src/current/gengnuplot.sh $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_488/src/current/gnu3d.dem $RPM_BUILD_ROOT/opt/iozone/bin/ mkdir -p $RPM_BUILD_ROOT/opt/iozone/docs cp $RPM_BUILD_DIR/iozone3_488/docs/IOzone_msword_98.pdf $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_488/docs/Run_rules.doc $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_488/docs/IOzone_msword_98.doc $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_488/docs/Iozone_ps.gz $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_488/src/current/Gnuplot.txt $RPM_BUILD_ROOT/opt/iozone/docs/ mkdir -p $RPM_BUILD_ROOT/opt/iozone/man/man1 cp $RPM_BUILD_DIR/iozone3_488/docs/iozone.1 $RPM_BUILD_ROOT/opt/iozone/man/man1/ ## ## FILES ## %files %attr(755,root,root) /opt/ ## ## CLEAN ## %clean rm -rf $RPM_BUILD_ROOT iozone3_488/docs/IOzone_msword_98.pdf0000644000175000017500000105233113573734166016632 0ustar cappscapps%PDF-1.2 %쏢 5 0 obj <> stream x]rݶ}WӉh H0ou̸&mt2YR-۲c9n^ 7<:Vi0<$k}fSڔWGot!ѓoMUe9y~$d=,6Bׅݦ-Ebsݱ(TݔuEWw۟vm;x7_BZN]%nveѕl]YԢ67;Yw޺RF7?6Uw(NBL(S֕Y.ٞtZ:u?ix1XTK;0]54ӄjsĦѭyPߏ(ytaeZUm6#lOOZIuSykfCm?poURfZM'V 3[f-k)NSewtQ[we#?ۢi[ͪh[ɾ4ngx4C\{tlȬ7ܙUӗK]CtE,7*7/U3ݰm_FS8<`Hn8~r12Ue/H'F љ^ժT+-;e`_Jz'Hw~Cx vE⭞z_ptb7{XBJnߙhD7l@YRsA}C;(*m%fXlͮR 6:}cK ĥk.&azU5t,u 1ח;c9۲aGT* UbO{gs3ILpJbG6ի&Nyg3[ $# e !iUD{[;؞ NsرGF7x%f3%(a?P,@ srDU.Z,=`5ij?@RvjB#Ō/=$ 8,puMH=C%dXcX6u{t uŁ.r2cJ3 L)aQ~Q8FSTZYظ!͸9bXBO\Tet*&M_'w84{q Qtf=AkK;  ךzjQ&N T?GWFq8y 箿y _ΠOv-{8JjM$6q;e*w!}`nhoQCKS3voUԓ}Q(%Ț"TwcDoc&Ą݂BDKp/?2njywSHJsе Xkhhɥf#aPKBSK:Xl|d? ];dsQT1Pc EOM`.E]Qq3Bҳa⃅_R6"8]/DÏCFEUwVLĚdי<:e@bM쒔2T-\JKPCD!53vE{3ۍ(vJ4%kT%Ġ { ~yOBgTAkW]MH@Z31A;)4V ȃ)W=jl8?[2R6*0~BI-C`qP- 쓉l=eȔ\H T( qRlcd6|r[#0lpuVU &|blc_bCʽIu- ^o`2]YީG*ε5 A&8tӉڵ9Dv t d1Q+ lwOKK }C0G,sZyl 5<#8#X*%gYC8OJ;dBrWa_BH}m1>.3*@BG |"$zPi()|Bxɉ Bӧtao#o~|0V{\8<]] H~l6+x@"|/GsD.RƊG{"(ꖬet56Az:~Mx_Z9ˆRV Wc7% 44k;Kl/ڮSqr",c6zwi3&$;,ia ?sY_9'N4 gY҃,~p;2L> E"~7H^e-t\cX=!v0B<_[|,d\+z۠f|řc쁫ޚ䲨dC@ mLp?Hخ`j#J2[X0(Ʉ̀Gjٚ府-#u3: 1Jl*BfY;,|x /!XLד+`IN\s @ aJS"3VHӑ uIFP.'72W*n= \a+WAw6|<+Km%z J1sTs;ALy5['g<)]&!@潤{ 8B2k[N&x&-ávԢ~׌ZnvZ:\q-4Aüjh1|$8?Pg4PJ*@DUF\c7nUMf?3./XgR9y%۫poܸm(WSp(!SIjnԎ?/ x_gC,hq KB+9o9YMM%6C[a!ZӶ,{R>Q>;(OIwSkFd1Jxfc2-['E/vUpo=‡^+F-53tm$bg%S`s`ra?WWf-yĚ!,Kz.Zotl0-Cj[]p4|YJλGqJi"2]`OuNM;zUuٹjB-j׏RRl4xY3ӻvM!O/J9ڬ;1țcUEUdj;'/@D蚬Xj w==B5%MՉP qOWL)'01Q@hB^\araMh `cv *Lvy t(х"/ȣqY5r9֪?ǢBU|+SE?'!ˎYBU2ٷ9С!G%^M2bV83{|+:m>Bdї?4!C`-T&vS1Q(:ܸӕq @Eg38VUP^cN7Ny[NWy|'8JkiE\%*O*:,NBO00DPE5l~Pu'%k^원m ɞh?GY敱He|$6cR8CpRffi[C"I%}J q&ԩZr|pU̻1xcZSX>p|oacgI,ۦ'_ѓٓ3c9U=xg,oYPU6Q f99[bK'Bۼ)yGi~=R=]__{Wa^;q_Ra."61criB9md({5)UåuyAƸz#)8*%kAы~\ R)>*"W+3bWFO#` c Z5o\oR3 }UOjY/+^V(✦J֚}OkA&9z*lsO? +b!B\>0G|dyKːf&B)ϐM!o|f:wYSvX'1VBӊ{?p*, WLt.DQkU2q8 I} %\f6&Q@g?^U*endstream endobj 6 0 obj 4650 endobj 18 0 obj <> stream x\rݶ}WӉhՏgҤuq:]bY-)JI`o y| E .{MY){qh{swyQW(ol>?9zLM_ő(ROFȺ~ӊ؜9wwOӤrMڴ98n-rn[WEnݺ{we[퍻wcYTJT ݱEەNE[RǾHWlwǪ۪jowU*)jƣ6eٵSQU-z=1굛Nzb]E3le} =IJ^8{f;͌q򅿽Ǣ-k7fv췱޸%z6튦kZdoNg8vZ6 [k~}ݾâeMMu`_Mܲ%=րT ؚ{=iq5l|aғ L];;{&^D7oL-?@ؼXh;x#}oh++J&wÄX/b\%16>eweX@ncQDJee$$ymDgZ@;EA'b&E`_xuzL1,e됕Fp֞ySBߥobbd$Z^=1r9tu lN@?8<(%iH$]nhDK rȉyRS>z/!_4B3jI]pًgLF\ck0>xqc77iH:oO/[YfGӨ+3engrfc=k\d :#ƍ)65EӶ"o57| Ǡ Sƾ GEĮ$1/ewi@™p~!ϒnd0T{ " Asy") 0q+ʺ,R Hb7\ŗ|AoF3@"< 0lfI[X麭dm}$#kn߿4H_H@~,_YFZQ;( _#kuK@4-U½K$5ȦAD3QEfV6#\ꦬbU]kt7E-r<"_j('G>lʮ̄MW@!/>s(}Ǵ 49> =پN3r9ݞjBKo&WZH|***zS%6,uEHcFjvUFyB~XQsӋҬcN5J-^&f=[}_s5zY:QVmźZ=j Gv;>VUEOVm߰WO]Go鋰q])͚SrjSu&wcjM/޹{59ͬuoo>cVpdGLJֽe#]<3z|:dߚhC' [+x4]-mhn ޔ5 +]bZc+4.`HC^'.6xW tf>MڷWm ǑCy*ʺ.\U6ߤǗo>֔3ea8Nԥ($-3PZN]96kП)e%VP j?@3>:=GrLDqG+@dQ͈w58mP0A  ql7mX i@%J6V(9? :iO4`Y,nRIsWi4$>^2 jɂtTd)*H0}еq ҋzN NyJ2(;qsN9^u ˰vߊKς!֗]-D!Π"JSQ2>`NOFb^,(8ZߞĜQTŴP^?[rvxک旫@LݐjLfX@G:~>AOk+ hw'~jCb}/fY Ѫq%yI Ha(<0 `|qTijaѪ#*(i>[)񺢉-L/Q.ܕgA=J33{rbzL@ TX3tWH˯]6bU+%0{T7J@^zjX᣹N OKL ÔU͉WlO[Rˉu9WՀƠ]SN?}F3ŇR?;9*ttJ'{*Q2MZA)g Q;)oi(*$GҠqJԖ0[у:q9aU,ݼv7/ݕep$A N^o§3 2t>m\4׬:>%dYv].jSrj r~?*fQa2> stream x]vܶ}W3kE4I%mVoIW(+MKUˊȉhq!gFϐ l}n,O_L?}䇓 OO|ٝО?;ӪnaNj:=u9ݞSQU3:qz.W'~[} g3Q4]SoU]Smn(}w~{&{}GYo~BH!Z^gu!E%uI/_vwl˲z(`u?|R}z8b*†Rd97ۺVnް{4r|,P-;o͍Ct=dQ]+{;khtU㲩ͫm.-;{/u8g]v]oޚy Vԏ+j~P͓ؼ6dz o1b?SWߚ>e5U(=Vey;:HyNtt) 9Tu͛'^X/2JL]E#-%h~Ws?T-zgzwlϚSu:zؠ5k.D.{'סVǝ4Cn˱CuSt31na35^{wp.1  3>Ponj]iN 'xC ."v-ڌDY;`* F$p]2)[I,M {*^7=, e]UW5Z\.i4]py%˦Bvq-`FO.y>cU-Ȱ,3@i<(iG}mꇖAC(tOwR4daVxˆ@IþsA[{ .g ݆ȫ{!lY\RS.pNSXzY`d%E=jfh:MY0ՃXwFGP\bl_% [maEڼJv}}|K CkqŨAK@AkڙմZ}ËthɁxfA:@B:~Дy+}.Ѳ"1R,,* d./L6nW6Z qdž۰G=Ͷ>ŵ$8ws_䃽Ё|c8\Qa*Yt voҚWYf~~V'fx,:cYԸ-1֍H/|JFiJ!#j:vsAQH vGckᑞԬO棌eC6S-@hSfGx7shHrndR4 ׃S|9;YKi^I|ՍV2DWԂ Wܗ1M?T1y0!O>#z< kAП}in#aZ0ws;~-j Y9e4ݘOߞ4^%bjVmGjoQ{'Ӟ3Z3zl766lEw=J@? rMQJ/tDғ|>,L^ !zP]p9j#,yEAE)diȋ!z5ecaCSdZm;Ess될p!D8e_:!i!J%z-myj55_ |5G:fBhƙ!ZG)l90iZ/.*9; ?% 6)hyH>yʢYw-3pZ%$[kWlb;zOՏְ{J;d#}kOz*a-e/z8`aD=D]o-8p=|],f ꞏRrhB0? 茅Y:&ϑz$$,~ ;} gD&xC+-dѕCK{D2+J Oupo;ml`>7,͎1ζv}+Wq=AUgub޷1A z^%hr#u^eru6>6\haj1>"Dvi>1ӎzk%Pֱs7&y^xb=}|ˊ _Z4ٞqH ܗd^fAP4ME % ,E#\߅Ɓ"b2۴ML ?&Of!fQBHSxރ Cm"UNHȉ1`z P};rUּ0ǘJL6-v(WW\ԩbxRg j$;`b`E3˜d!+nff',Qddt$/ p+:'L㟲RaEݑ^//P @Zu%`An{^ؘ^[P' #N3 ܬ;t2Δy@gV9?8=dx*3~?(s1<<c0p~bGb$|_@T d#%+ÚqrE6!Qz\ ܟ]1ޚIgx5(ԭp"yM!g@uXl㺫 s3ql6#؝Pe-}ՁN:˥`L@5g2]  KφH* #/ 1=,s.jhhV[#t,_wzň9UфꆥrH]M,Tn?W?/Rh6e钶U=*c6s⃒8?T+QZIZGBna‡tNYA9Ch4hn?`y5a}Mi6:~$8IlX sŨԏ)Åyu +&|z֍XS0 莿{#v!YN8)riU`+ZYWJ~Cz:lN;Q$+^(=Sq]8| x(c#éɷGβ7 y} l蒰AJn8ՄjD k~Jvyms^TAóL#pk归ٽc kV$!e~1 $'ZyEU"ђWvl}a`vu ;af3IM_: -⌲%SM6+ХS=C ݝ-⢿O{sbOTSjz,Oz0t$*hTiFCb{%؇cj}HYc-:0 Z8L M -#E4cA@;]tq%H([e+u~, ;!b $|=kǢm US]cCƆ9v\Ժ.D%IX ʇ?;8 ¾ઐZLnu/RiGR]RISq挽ƣ~t<J@ c8cglCJ_"5Uwji䄥>5oҁ>r,(\5'o6褷|<+&JW۳^풍mLn_Ӄ(*ftY#:?c۟)"$\[hEc;^ tbZij]E,a=,6s7FV*-qQJi%=";NqU0֋ &K4ouG6)?,1Ś \ȝV cIA=v#\\ ?y(_>3 i0ʂ)z9\3G,-gm}-2#!̵~[kw.Ր/;49gB;^16tUKI7H!Tǔl4ݤuq'HKEh3j68_ಌF,#n rkWnm|@uO.٤|*\4M`{/ ]2cB! %t;(DEG6l|i 0DEH5+Ӑ0ƌ,? VߑI?ޗ-&}ڮP\fcQA,[ TY钲#%f&?;Y`ݓOV^ٮŐ>E(Dk5ݔ^=8tzO8})#:A2a6~P @@xPxXP×hxLkо+gX YcEQ="`$km{, ȋ*59"t줂S@VogKc6[_^-J*&l7dt#j4VrbվoeCoNsms k{ J4 ⹲E$GہP*ZikT7;kl xB*QP?X,هrRg00 R! s!l}2C2]3nfhq(@o0UO>^x2_JgF[a:tt]Sx_{(W}(>um!V7n |S/Im[ASw9W3>{&s h`Rt uU๩SդҠAg1'O; W^wЖr`هָ`zRb/ 4P"C(d ;5;cC%=EVDыpj:aѪ;hg<rje(6RQ"yҎ֪7QGI C܃:pD:+LB(s`ǀ#+19D/Ӌ}⦔%;^B@1*}IEay,3׊\0*n"*(^N @[jS{mK4be43HL[XX9_UURzqU+ї`dGZrفKHpd5 dQF(Ez2|q1v\EKZu6展Ԭ+'Suzendstream endobj 23 0 obj 5447 endobj 26 0 obj <> stream x]r}W)M))JI]v%QhQ`i3RB5`tYQǯ.~=jg>~糣Ͽ뎇lhYq: qW.Ϟtړ<뚡jjˊiUQ:2oOrgw}jO!+:y+b|eQf]ϮΪZνGmɋG]W<o|;kICVW,=vo5MZj~g}ʦFa35>uꉾh?ސM\_z_g;*&N %&O vW?hi4sSMW43s.j!4-A117`y6G^|w;ob rR u =u3H5{ڼVϗM>iYY ǧc<1(E+QcBUYeu|>T^4Y34'WfέAb 07wy)ߤh&UQ7pۮT}I%)~u^dCi>ʑn;u{j=9 +c|@q :`Y=4BS쵂]aN4Ls1Bvjt?=.V}Y֒Eʆ";iI֨vZ EV}5>R]ft,cFl/†-WA ~9~ ZԶ}iIЯg/|(Ҙ=h%k=+ԵH1u@T=ɻjkyDE5|5R>PJ `xSJM=#_r2MeSU|˼ ɜOziLYbG|d,xB1HpZuPtOs`;'u V eOvszj[a_?v0Y5<X+]BG0H`IE!})6,D4ATAFE!4DfF͋_IDs~2_yճˊm `^wS6dYSUnzrh]}trgjɲ"¼ -1Zgdl]m}ܷW3g-O,[K']HWcԓnv\F4 i3\ y3DG#$NLG,4GcIn!;xL"(v p.q%ya}}M}[(Zr 2B9 c*ٿ U Eg$u;9>]6մ"Xfd}VuC(|[6uqPP),dG+/D59>lnҍrYQ1…VRH=w*W[sM%u ~Hŋk jGs f(> ew0e`jGfO?[㳑/A5a c<%M2/Pz8LտbJᶨC(ͱL,A:aeeuufj(hY̢x+5CYA9^(9š#lE&3YΙ y;PB% r8#>o!d< Ⱥ`[wܒ$ǍE9tUJ+ 3Y_sb;1")NA"IbYBnС'D. Y?cDU.9bʊ733=?&bВH8ͫ-FfC1=ɱ&1_7}"4`A|zvts#jPέerdb /FX|+Ҳ5JЎ{SVUj? *9+)3qVDhΪlPM ?(i5y i(֟:mթZe>e !5oՖF Gdrn2!@ʕlVZ+l^V,rfԒܻz剩k>0B*X)2*4u!'Ȇ :dă67&ӶRy+ yލbͲnN,YZҖlWNjcǗȗU#__f=e n鲃e34t-]vKt\iev.1̋escoQݩ?l1z|[Ky.:Dl|Bژ7%gkIU:@x!msK| -2,@$!P.CdZZ̢U{?f ʛJԚ hx<6-5^DO.Ϩ$~Oˠri?Fʶz3}7II g_4{]-CO5T ×- cns[n{]6 eo~zϷ7q©+>ZoIIVy(fdؼ`dXRyMjh_\^=n0tWU77TcQWgkGYGkbU½7#AMv]ٻi1Qzʰec Dh<@9v&x$"3t!xzle8Y a:Wph2I lrCLACnDx#yz -Ff1Hd9ݨp.[,(@m皺ǎ!:4q +=~@(pRD&M^;po}uqZbh0 YH%h:otvW=K(hC;õ|v@*# ("SOl+bNa'5asֱ@"e"D"m?+ZC m9Ye>dM"4FBy>C٦I,=l\ӃJvrn˝6ya*!b15-u#|j%fCe23+TaI$YU"yV> . -^x+]a4vPFB ΰpi8 b}x+\eYa[QCFnM4[):b|9+lwN/IžgvN []t^@g唭QS xcJcb.bobEDUx1.*suʺTsY(r0,f,|!d8-Xa.!}+y̧nP$']K^UFl1Cq:e]Y xD,C /iIbT-(^)dY1@Ig ~KD:vB d}QҌjd[Y!.F¸ot|~YZG\T<]ҨޘЮJ2|R6r5iRZΜh^SQ\HT@WyO6΃U25Slq_]r|"$4o}s(w3WޭE +*JiLc+ WJ˔PlO̜PkM6%$x3xQE!SpQ"DJo)+"R94YQ+vN][&E&dH f|Ց:}ן>r+iڻ|[ 21ᠸP'8DAiSr}"0xEVD]Á`Bފ+)$`'%"{u8ŭwXE3nOC֊|9>7mqL1ۆha2c>~9 LIJ3a_ȸq!zzy~ɬcI].7MR*"q \juc7sjQa׸6J Mj^A.*&RdmYR#^~!cT@(,wTyvOmendstream endobj 27 0 obj 5381 endobj 30 0 obj <> stream x]IwݶW,18{mq+MSGlI-O.{  >$߫6Ma߽fY~8yuỳMw?W>lӶ:MیS랆ƲmW/9ggpH$Z%(I@Ǭh =Ovoy]?JhU7ͿI&|69ƄpHF"r*;rj:~}EM%J6Lfk]z}nxT3(2S_tl_n4%kR-3wwGvu-9s5ohG뷆ed]]}ʧ?~bmO\w=&&4lЗGcǧlO]UӴ[dV*~kRic(Q}}HjgdZ7Y5PUۼxK(In?6-`3n0靡g@2Y6]"KF;6ٿk)40mVnJ]G5ԒAn vssuYӨi돊Ka  3'hR\>lO3^Ngkѧ٫ԍo|~z!^ c?~HJ5X2Ylyr7j=nC 4A 2JHˈy d(`SAo3+hFytvJhV2 "h|6PݶCUiT8d8|Utz-mn3]7˚F_ӗ"C_4/PńgKnV=*2dH}dP1 i S@qap(_pK{C˗]hC|*.qw4`#!iS>^=YSr C{.4٦5}#XX=6i[cl'EC{ : K7 C6h"ò ׈w&(wI,RԤN3t\(9Rg 3yP~JeZI5Ylf?'MEݬҶAW5odE//?t=IH zjq꼛ۇ'H7jp*vi.کw}ou{%Ƙ'CHT ʦl&, 8lfeU'!/@zdL`K2N$b?)l˪X:W9|<׀X91 ߐu~pSBmhZP2VU`T vRNWM*myLKPSVq?8m ?#UQ K0 B耡q2!b1 OAS^x_c?'6J(VOa5 % pMSکp~m`iG+DJyA akM$&0KeZ6)2wWNU#Έ[Y3D vkGR& 9ybz.Ӛ3؊ `dn>a.QDu=Ҟc/_;T e<'INAHs@@ D&  ;SIDNU,IT–: +a@'It=Y%l4鋴 dZw= ]*p'݆.U(jUSn-pXWk|[I+k,/`ijk$ōwtA1# BӶl>0HPš>;Xdh*|T3V32Ǝ"Xg}G4 >U7e:B)5bjKeA__.Z<6RT `͘AZyi@͢FҩVoizQ-F* [zT.D3-sdk%fpzBnk1F2<7ǜzM%6xkV>EǢ-0ؠS#& IeS(ԃ,vẊgf jʁ'@H)6%}Lm!q6= mLuk8,۪Q/<<>Q," fɈ0(2,DL}Oǜ p7 ׼X}h+n3CYuRIbCT]Sghk^wg u!L%PZs ].ܪ?87\V=gY!Xx NSX"j"NJVۣZJ a;]DܾI/#V]g]?bS3G{lCZ x7uCNpE_)K#>c*|iN"v+OcbSLA`P)m _ e3Sw/Vi$ϞDYnATxP Ra VT],') ]05RZ];:^_ \`endstream endobj 31 0 obj 4366 endobj 34 0 obj <> stream x\KwܶW9Yt&'CH.iq*mrKl%|@3,2}||) Qm_7OO^B _lxzv]9<EYVCU]t]iEg9}qf'jk}k Q^e6efP/vht 1{n ToTJ y lS ; 5uMh/"eUNl[ЩԽwENWsӂhZOG*Z]6}[4m+{qNoґJ#8OPs,TgNthvrRMQr1̓ ȫP^jq"que6K{kVU8籿H 1u9wdϝdK7?lEզ]N6vG>O4'{&5]xlOd9jAB"1!cH#=E88~&hz $hk+W\AESh-ݫ<3m@? WBr. -uَ]鱏oժ\l!s"D"bĩW4Ғo^Щ^^ݺK_Blnn-H> P{ M 6o]#.$|X`g=.g3 tkt<#ähLI5# -zj݊k<#ghԖC&qc`ah|+2a~QoϷ4C`Bax de/8%\6E"s%$ !\fK<7#;ߛq&ocUj]A%$7ٔ2O{Z ';Q|YP]cFj YI(#vտ 48.@Cab{iC8oD2& V@({Hz0H+:L; p⬝sjάw-v﻽6+~Kϩce #o cpªz ^]6J y"MypdVRH.*\荷sY숳Dv?.Vy3Q̦겫A\jNQ찟´UԼɤw^>1 $3KMy޸\SYRmۯ] ٤H{yChE9(9?V&հwVKaQ1*c-pǗp#9^7J*6DF($~MiLSE oHRE,rA *$lV#*=>wiR99-L~uY {AGHEBٞŠowo_U5oJJ ӏ I!xU$rX$lw. S8DyJwv#haԇQOӯ6MFg҃1a"huzE'pOk6߾36/]h# L'\&;CG=^wm(O`jfƤъrbZшgF?j'SmSn S0%A).x:1RIm!AMIgz찉rF%K>LÄdȒW; M|I U7 :O븾K;0O$Ta3b%~I8_zs5o4Bp(U UnX%ܩ.(B4Zxxဩb=fa=Sط.@zP|},x.,?Pzh > M0~=s/8=}DB֎bD&VHX6}Kpk+ g^"u߿t(Ư}=_ـtB-6u 0$h/nmyPl/+ (pGSse3[l3sC[:̢GRo. pynd:ZNJ{f%KH[b≺kb}b}tVs 9ҿ)fuC!c%V,+AafQ%.K-2MMh!*`!i}JDX]p\~C%# u$ $\{|ڄZ>(*,uq̕p(.ȍ^Wcs`L$3V"GUSK_PP.#!<=]Hids~| ++&w㢗MlD} r4i8CX 8qƞU5.R_ i+⚙ dN8ܕlNa= 1ëty /l *;V #XUi1pG+IV)H(BJ89Z€k}<%sW0#] G?q:z:Ta1KXS:SvEB }_= l?0NI6QTB٥CK[I1%jӁ ,c`ox״yBZs ̥[X)#߄ mOPcTf,|$nA\ &c00LW%Ac/HJXgS@Me1Swt_I_y_$geD |"t3ƮJII15D_ >60e!AC,ù~ZSZ΀~xzWendstream endobj 35 0 obj 3962 endobj 38 0 obj <> stream x\[sܶ~ׯ?t9E5&uTt:$NdY/.H.xɥwj?x w.\Hۿśwg?B śݧg|]єgRo]m6U,wo{+Y(;ا*{0QD-*ԍ}'L7^Y^oVK_?Q*7TO/YnSؿ Uvhy]WJZCmG7FiEݧe(JY%*~] |IaTOfOҨoC!RkC&!Zht;,DarW&ؿfW7Erj.S&oE9c4(8OsU44v#s1xGKVJk$[>oY+0ao Bcؠ죒Mb/OKzىʭtYT9ѱB\(i2pG T<%)!)ܓP9(z.; lT#R) x*_L$&ʹƲ.+|"|Hz:r$mD#+}8Eᡰ\h3|寠q틏,'Yk/ߚ 8(؋+,]25 q̀Sb"yC&qMՉ DܑD>lF Zo뼨 t{Lϐ?.67N&iZ*-sR_҇ ^nHD#[ f^Csi㛢V04 [R-  8bJ#񂓞i۫7}Sga4mߡy0~6.LSfxw0H:hmz1LSۘ 'jUP:%<"3|Ay<JUS{pF0U7, քњ D*w~, hh 9:=| p;lᕀFZN5_D-fv FnO*#̃yAzk$.-k:W&p­ :}w+׆E7\9"wp7f$ ~70N&fx`5MY:blDcR, Rj=4ֺ+P@bLFf(@ͫʵORNGr1x@-@@Z@*DДÔ)J#&|a,̕D-o&S)᠈yPdCNM:DT)rӰ!IgmnTCIƟ>—f/uVqJlcZE>̈́*Y #7.M"g}FE VBlpsw 0xJ90q<v JaMlkŠl ΆN9T>%s:vӅI&0l83p,Q1/vwx ۯ|C>*U8lJoĭ9$p͐\[6f{u&Bt ɥ#ON >{4(R;ְu m> 愺&:Ԩ*C8#|qB )%"Z?rԕPM&VnjJMwͱ)Eʛu(CF}O Ή7xt~aomo1s\0!r܌6P¬ƭ/Y>:so, sx=E?"R d# ˻fd \=oRC50.!"3Y0AJY'h^ 78?R -ˎ6\arD+h-q쏎F7!2+7l|$2@SUIL<@Duў%%w5J$,dZ)Mn"`+|J0\CY?au> y ~^*yqk&_.$5/Hu-PPJԏ]մ1;);.9$Ӂl3 |Ym{kQG KyJ4N. KZ;oͣg1P'\J 8J$d0 탙v1bt$QX$~kU%tl-3Gor/otةĭg=#t 80%A>Q~3,4F% c9OLt-k:>6@r"F~ӊ BDC\^1:H!J~OCigԔES~4 ~i1}lۿUg kwwF`A&fTwRT3Ĺ)V4&ڤj7,2]-Hn0"Y4 -Bzmt.bi=.3 /t0"J+%Pãh8#\rJ4*bjbK~BX [vOlO%d<6=nQV;cl0&"m]ԶFK9Es؋;t /.Ӟ;Bۻ?4^>H=F;v~R'0U ysKs#AF1`L$A'5l,l\,;<.11m=JJ@EACH$@D޳[ּ#ǰ ٟ}]endstream endobj 39 0 obj 3409 endobj 42 0 obj <> stream x]ےܶ}߯*Te` H0oIrqK\*j][ڕֻArFrĪG!6rt~Ʉ7Ygp#TO{>OԢ.7'RdY}+7Rj!zSLTܜ>v++oȴfEdl/)sގ^v{f/boeye3,De}*ߞًLVn*!uUVFahwݫE=}upiwPR0@t7[q~cj}n+;Y YՋ{M=@^[Y]Z.5~U36,ɕ{˥:lk'u%6UVOD$HR|Ҳ3!E^UJdz{}ץk'K`a؎5V&{fsiaX)ש5&WE^Lir Z)Enho@}܋'8eL72i)je}A+QV4L%*x,믚{(ەn!.Nzm.R#mfHI3_t,TLߗ}[UrVھccT玔Ya$L;_f01Zc(0 grͱ`>X>iڮiV5\i#gΑPUzFcJ벊[n@;kY)Nfmh7gp'\؀sĢ0~:9aD&*4h zD)SW5lxFd-r>c23Qך @"]cĪkS.W ɈΰhgwWN$zO,?1-Lr9GB6X.E~hfnWBC7W)yҔX<y_f7PؿxJ$jAs e 6ei$YYiF2iLЍFo83N۞,tIX B{8Ah PxAZ9a~{N{gf)MW{A^%$r(]![峛#.Zm#!p5vSЀ=Yo( gu2y1Wr' qʆ"b. a8B"0ynK>4}t# DUCn(PF ⓝ/1kpWTeVVχ햼}}=bE6#>0H.B whהCދ}K"\Mf$eAJ51Q$Bp$wGRYY9wn^`\B-)T-^J3zc 3"r$Vvg49s=hlLĤxYR5`hbS覫+Uh)L3إHuUE/͕~Ϡt @w.Qkk%aD%C戊(77#UO_'@ވPPw$ O[0H;P+T dwÖ>m3!+;®qog~@N=]F6]><_$ɡZBե-ExrDۄNwTY5T{@}KSJ:Ϝ(4_cPK#T\ I7߀ͧS#Fz=$zTܭ@LSN4W.<$"E16LVn%_'M&ʚDŽ>ʘx7Y akǎ/|Ǟy^8Y#[N% 瑜awPs6`N>Kr:"0[;lT®3ռ)D!h=V=B^,S]Ъ9 [T: @>&Td-^v}GjHz ĭoQ w.`&@J̅&=rTRȌs*[b8m%}6 BR)fY̝L!{wq|"I5E} Em!Pt.2~ȦP%xSF"duo@@hiq*!c ѱGGgkd^R ċ`C5- \QJ5`3"(d1Q P ]S"mч!V236Ix% xyW fyLlkz&nI"0:6<{%Rbk$]]YA?hT=DRfnƁnEɧ!>/)Yd%MUX=΢2em"˰: ~. *^ >GG?׹X57.Y> 3~(Ľ;0,"5tހ&&gJ̰(F{r'~Io8]D|m >(R]Gry>qgʥ'EN; ^F<x 4'N,bJd-|tzoˡ2endstream endobj 43 0 obj 3864 endobj 46 0 obj <> stream x]Yܶ~_1U~0o-r;v%YW.aln"o$rHٕ4⁣_\b\>=;˳>? g (کɇaujvO +U]הX7^!;Ty3^5+rhX_gݮjP}[0>Ed]F Yu[t27eר`|̻h:jΎc6{JW.'.f4g#(͗5o }3WM v?7]CKE,HzwZ-F~)GijsOeިTrS]6cdG'BѺ/zY]}_UiڥԵa W~&Jo"Y˿dU^4ء5eZ`df8C 3-2 F8`&P9-зyG2gKc0ꥹ{ydˢgY>gGxCTC}\u} z`ttl 7KH_k  9w[+celc|)(XW,QB! 'L^)-Ӭ^tMf_=^n 26aYuͦn@ Ffۏ kH\scŵ6$ʾa8v_sl&S8Q͊BU +L" a6e X4<0}=o;e] m"iMadA~nkF5י['kB# b#GADYoBArc9dBm)5鞚vs$l,|;-ptYY &2^->nHOXEUٷ$Z @`^#\xcoutLʌp /xss~P'IIQ/h'B Kl8H;0 h[Z}-ɼHP?2-ў)XHCa?ņZRєӿdGT'celNзqeȵ X'6^f mv yҍR]_/F˺$ 1 4K2 G=Z8 3|l 4K_hXGYSJ?Ĝ7C߭QӎK@{숋#Sg(Yަjz_ԓmఝAmhai}/N^Vs;zV'VOC_EWװn6dא>s(&OMl@^_8hQWRulj'O~d =Nk`MawXc+pkԠ"BtawXOzzj6);l[Vv;u=lA[oc'c`Rv2*:' r@HlXCGLY9gqYva. 51v%r1fу9Ae!C>mNk+I\&FW[b$Nw I {|[MK` Δ 5;q*[#\/m -a U1s2Ḗ]MzmExKg(x+a&8l xB^ ]>Ty(U?[903Ex0b%P\V,,qKRR!$ӗ}4 SRs̐r 5qHdm*hzuCm&ZpCuj=!ɧ~=A<7AoAZ˴&~6c9[ujQsSq >X*D WKA.ܓq&iHOl;=-<<*χnj\ S}پ,EBJ 7tYpm>l =@~ԚcPC@`SkBtR=SܡaDJw.9U9(MLrOX`%uOy#GpFub ^Q:f  äj0;3N ;Զu<rx>[.^ꊽ+%#贻vzB?{ |%IUAAЃ{€#;g8l-bN2G@_OTvh nD!*Ri>ac4W zB(%$cM4&{Qg# VCoMcŊZ1Gu{NUafm_ j:M+Vz Rlg@+? ۤrx뒩٥rYY$_9%,`1;<'Vd->8ń1 7ѹ%hr3s W'$NUN RxS.ƚeĬ|/mu=L9~;IMB(VdK`!ޘb}rC`)mؚ ^壒aJls[#y>)L?aHNk9[UW eU/~5yQQzЧ0osBb>pVp5ܘt*tmet6֭qES$\C@j+|'b_h89ɾ2f}LBT0*vIBwe3NJJ:pJJ|\'Z}@;6[39ә\hi &})R1xf-~ZwDݏJ a^I}6DXۏBb|f׭[[ޮ k>HWDUE>Q,dvvwƴ(W6:LU+:#{WP0M+ 3iǭ!H24y6 s В8(&.kD.f(_i"~zendstream endobj 47 0 obj 4241 endobj 50 0 obj <> stream xY[o4~_1oLk'"E-mvٶvۢ뱓89̬ />>\rL4Kj^ޝ/n{7W˗Y:rn!M(Q94"_hvuQՒYYUw^]W eLZVud+mUsf4֠*ZٶzL5F :c' ~m4BsnUu0-4֯?̲j^R޻ʻ297("qQ%lKSSiA Ogu.ꢬW B$Ю-sƵӭnSլ^TVa#1D^.N!ְ2OF\7 k»{.KvHa .w禎軫cP Om2ЫuDFMt?}aJFV ɯ\> բт3THd!SJdV=z"gZ6X5 ~9IH)f9Z֝Vv)g$J`SJd|=d&"woHِ:%PQ&řP ͇B4 Q)v(A z@2a "4ܐ =` "7U˸RARtP%C)V0eR#m5%ˌs4b*33ώseU aΛUj@g%pQꜣp:?+Vש7Y1:DLLŇ#7`(@QnȧԖ,Bk`!pbohC~[DˇS5A ԙB"6bs˗{?w&Pym wj'a Lrh! G^lt͛ݜ~ڿM@U1҆R5%_TʀcЈrynN nS4g/Sm+nu "],F?.=I 'p}NFq wC7N2ƒE$%!4 h=I9b%IJNp]ص‰CZA?a_~j(4z۔gIW x2%DA1RG P0?F1AЩcm'B=Wa zJ/6zy endstream endobj 51 0 obj 1522 endobj 54 0 obj <> stream xXr7}ܡ uk[VdT<`cc1پ>]36g$uQ9WCxrx;X&ӫax`tp>Ws΍83հ^0b0l fw1 ƕ2z|Kf5r)#t %T{vI2! `ga͹5ѦvfH~"75p`Ãgôɸ6b1 ylu|LJ%z9y;FA3Ϡ4 i&j@Τcؽ,jyM JΓA7"Gdc1}StQF:i-!_-}1TH<7Rt=+v݂X7D;BJP $vvH{q%FS=Kg&OmnlWL9u8?_gè`5X}_'Q(g $Q1J(@iKçt_\wjKB: cVƽ `__)S:V#rQґAev\N̚?q6GW*yg[4_gXRx.qS6ʫ7Vjy} aB\І⛮Jz IZQgг3Tt? q:dl8xe ݅AY}.&:="qƉtzH;&N9*ӒXala*) <%ptr qV(HHdKDDT# D$/.A9ʮ 7=$E$JG+ܢԂe6$7t͆ ( ݌h'(Hc#NVDb "sLZENA ٲ9uUBTA|Y#L! ҊNd"eIV FX*V_?Zy61E.0rF- D@ڵ F%XGy *&!B m#!~G5#eKb:2Ւ? nO}'c ܧ ډևwtj4kk]+w ള^DbM)A TA!<:bB0!jjUT% VJMQI2ǡR.=R^ j1&km/Ԕ JMJ~"4+"4}@!|ֲF"@d͗*l%K wp/endstream endobj 55 0 obj 1746 endobj 60 0 obj <> stream xWMS7ϯqU#I*WD@`' bߧ.&U⩻z$}bd"u)]Ofs%s{#ݻ.:S ?hgՆ\,8m.:Bi %rm x6z9N0raA;vEWm`YQqmOˏÈR$kU=Y!,eO6\K< WifK5ٮR> u9XyѫsY大ѼsAҼɧY3;( wNbpΧm!1`ZM|cpIdsS2qtQlk]mNӸBP<4|1 .wٸ`\7¯9_)vPutYij6he Yq@v+ ̕dž%sЂ͵שHrZjA2\yd#2fct)aUË6{ڔX g} x*6^SoWhq7T/6xT9"lY5:+[r[I: lÚ&UJ>Z<㟙 K>z(>Q:ӄ!WѝlB'޴Lͫ/=So 1,$e&"fzSoB FFCԊSLu'Fd\ *!@O $D+:VCCyĸ\40^a$M;2έ)Z 9]ns<ΓjI^ZLwfu_endstream endobj 61 0 obj 1560 endobj 66 0 obj <> stream xWKo8 Wh/`Uǵ(·I2iw&$__!L(H#}cuǴaO9!7Ǩ6Bp!+>VA﫻*p x;],q$BY%ҶdݱY}Z.6bڔ[źUkZip׍˦BmMi7Zz_Vs뭪F7OMkxp*LHz|Oy[VKt +cQv1\zj'Sq3XŏrvXl Z׿hMsS{~3;"?NOw nB!YR'$|%|F=XSQOU!fXt_K#3c؆ITvBsfm03f\/7bdpn=o6qa"[1P%8]1~xrMendstream endobj 67 0 obj 1025 endobj 72 0 obj <> stream x[rS-,<V$V.Ka*U)RDQrЍA.Ÿb]ϸ/8|nKh;<^tRqz|ܪgapwwqL{rtaӝ]n8{1>Y;{gכm;fdϬwgsEw_*q͋n7;˸vn_}]jSUy~Kۗ^1gK3Y+豧{gJswI%A0YP?YsC ;=SQr-齄Q_ð/P?H*9 ro9h̝T{4=w%C fw>;h:Ms]<+&"ȀA/ 3Q#k Ѽ-%lP !RrА ~{ `'nU5i1+EF"dJ3bCVQ 4HmI{;Ps'N5tŭ~)*“2.>-H:L kvu)%$LIZQ9Bx0!|V+I2Ash HGúgy.[ rRL}E{@M *aoV"+"p]%ݯ±ͳ'Ļ%vv(>GB@]W:?x2|W!)雳.i"G9d͘Gqla<{KwhcG?pO 4Cs{~I]3c+20䁳s&NI` ~VƐO!h_E%l3< @#C2fJI J ф*y>„ Wt3#esO*D!txyTK{-@_QbZӋ'™cgh:<їQ>OG'p?$HL_曂S3RB襃; .nQPuBHA]`D Y8-5<ԓ+cSOo'H?=1e;W L٣0`Bf[k4U`&}O"LQ)1"Bh>DL+"FΘ镵AjBBN_Ũ+ N*VPm*fk$BQ :+zKI6tkH8ypƴP{ Ji3ZOʭ53ThZ ` ڨKtYJ꜏UPj-#  })s/ =:Ygx.a[1=p-=^ՒunHAsvGЂUc1zbSč4Sk,h"\l˹3߃P:~V(ؘaBvPE(>y*7 ȃ9#  #ne ~iSL݋UqH@#דUxgw'HңSⵅ5գ`.3qQe&tҗ3LH^aYNIR_`Y$>S.;dGeX:rg A_})w3eu~ٜLN-U*^3#B^:cu}rIYp.(n]j__[!\\!cbpa#: VWP,TE,EX<3[.`F1+1=.94ujg.߱uapȫP7 \3WփIhwEpVD]}9P{G:=ěIpE]D!ErǶMigN3!P 5=U\^{6 `5ۊe¨a;O3OT-JZ U&O RJd f rMf}Kim+_N)#.N3nЕ}<ሷ.tJO!Ǥ-'TWH l ] zgk݃a7W!Vt ʠhԷP"!E,spmk0lՉdJgiD{cvO]cEi3T:cgl4q6d'$Wxm,  Gh\Ţj)HOz9_m˥3Yn>FbԾ?<.H;}rE }wzs0_61xf|Q;GCscT0V0._l4!\)5ۿ.B=u1[vhfrELz( 7xCW!ZB̈-§-ܧѴf[».KpMe>lބQB:Fc\ i7~뭌q ѐ~!wE5F%M)4GD ǍA߂򠏻 %i0+.{A1$z9 帗xBnba|bJK-J<лvy4-p,ᡑyJvDZ4V:Pt>@܄)V$AʍP@㎀ 8R̆f3ٴb?e3HӻLiQMN-"Q`ha+Ʒ1)_8?x ½*endstream endobj 73 0 obj 2966 endobj 80 0 obj <> stream x]K_q"}9B$ d1kzHF#ْ$,{B"wd֣ꫯr/|{ag77ߗ]>x6`fdžqE7ZofW⻝`bPs%_}}vq8gr^)#8L %]s>Hmp?)~p. O&z/wq4ٷ _'~aLşv|&'bWqW3=#zQus؜ŷټWcfO[q[ls==m&suWc/<0ePǃe}6^Ѩ|tab?xJFGڹtˠ%۟w<$]HAs282Bvon9wotx{{3Z YEX$Oo7ts9BhZY;$)gA`<3EnG9PWšKxr4,?r1cJE.vMtzV S`,4ʟD+5y\E ?iT0  (0gz"8 2Ir/AwSx 0 ^jܲK 7gY%uoAo`gB:eWTx*ڛ̓&.Ein@bw+=%}6+ͤqɉ~D4?^ɕZP=K:w2;Tnu/އS#ٰ]c4QXHUe)a"p,< lJ,vPh÷ e$~QYXA lrf:!No( hD=8; $'3:m.E{WUP.1ŀ#]B}MڍB}*BxyhPAIi.Ћw/+$Fγo)Z-q%Ú("EQ%|23VmhKV"`Mgb^*? ]zK5ܽ!T6ɜVktq@_8! ert2q5,%ڒTGvʬ;sJ_SM M/j"e:z9ϒfo@$cccc]6?As7Ƭ~&.#i)ǡp6^l8ъH|JXl(6NgEfG* e`Oֵ3f8&\J6AC ]\Cg)^<+Q0APJCj0S1m>~6PQ'yx5f HFx[ \wLၺ,;7d(Yό҃k@rA|ZD Kxr"z(byΊKW/ԋ b^9w]HDB^C 6=nD$B=8: vj;0OҮWгƋKUԁ6Cwf㴺t8Y޷T v/a` Z*j)S`?a [f*L yxݘ0TFG2Qꣁ&|ۓ_M4q}aTħj$uC6 ;48Rk{]UZeKvMӤGuM&qTX(\Y2f5:Jp`)/OlB8  ==.q3٭\LZ"4cq6qB/[0. jD4<"NG S!֍G"ȷVW)]/*(Aģg5j%S ihyOzƟOM@Qi"dl`BfgCq%dVԙ6oșw* 6f+[Tf.Ri;=h|B (ؖTWK_,0avb(H/by\\KV[sK;͝#hZBv|R S.0:O}JZյf҈a=`u]x *`s.`jc'΢:ƪc̓rFT_I°js ^F.f=kP4!+lTDzKGNX{d=zEܝ~j9F$f>5{E Of/G2F(,Eu(s5$An\֜NJdQQ3Aة[r\<^XcN U˯^[yUn]q\ଗl@cEG5oki3uET'H2A/xgլ!k{,z$' Ï@ I1P4 _*?vu@qs):HvϤ|EPڅF}\~$BџӤ%[MŢj9XƐ< ]4yY.:uX'AZZң}a/ 'a򽘣oowB)oԸ{yoݖޙǟ*zZsFgv%=qZ[l{9e.62G^żNm@4cɹ䨌A]^ഐndX!WsA|Abgs-ڄZth1e[—.ޥSZThQE=|{6-68pH=y["SV-"GVMUsX# &Vy&hO endstream endobj 81 0 obj 4884 endobj 86 0 obj <> stream x}N 1+S\^춢!H 66bnKαި+׮ x8&Qdv3 "4 eTh.qω&*pp>Fߪ-Q:wqz Gi3-<1endstream endobj 87 0 obj 148 endobj 93 0 obj <> stream x}0 w?m?`ci7RHR&tZ }̅:cB\.s10%|%Ӏ*bL r=NNGx1Vw9H \ǚ[ީ\̩9n摞c1endstream endobj 94 0 obj 150 endobj 100 0 obj <> stream x]n$}W v$6F]I^$o!ސMVgOƍ9}~"nb3R(m9}yݾoԍnT]+띨f>}˶؛l;0LnnG\04nݾX7MjK48qltNJS]Bn/훬W{ۓ+*>O1ћ瑑ނV7||5УumluU۵;a_ScWDȩk-BJ\"? ;?i{m97>ݽhtXu?X?ARϝvϿLovIm][}_7տӫϰ(3R*jwS[Mt֛z(++1CI2,"5CۭIatVo7f/}lX 鵧;]svǑQ`rFT/Gir,ޝAy٦~@%\pthQBDThgH݌R"}5X|cN[;Z7F21ȣNNXf: M.FpAvZ^ $c3}kY5McDJo?)a\MPc }`:Umny_Nԟ(~'<@Frs352WY7o|i^nWdzE sѓu*mʈNE͋NVbjG/iJ]Di~㔾]8l'du`LM@('T1D;k]~WQ`ȧD_gCa7\̋)6 rSg,)W.ZwzGh^1 F-h{;o/:0 5(3kt*:Q2L=ُ|oA1)1`L Awz_O=30g9 SOfƃ;[kD-o.3 UE4L߰O$s--D""P,Pzq8vK,ȥ \g$@0/S앱%NiЌЎ&};xȒяve- b:Bf\?Y^m4>ZYWbjf ||Bə+$¸"0B<ƁIFi 8:y|L]  n%.96[H#N%\PuD3C6gPZ+ܾm:J*"(P^Î742FϏwHWo=aso$>yͿ=!3@.W ĿUϻQpa$ rPp'u(0zHp.ӀU8-B8URX!d0R*nŠHD+EW8tȌDџS/@1pu+[3&9NՌ&,)%R*A+u=YoF5Ox{#&Np__v g=F#+T_Fy8렿8_sEPJL'$=0꒣PoV 4#H.8 `$֔`?vK boA\ź+_YL3M`Ke@ɫj#hsPyy}-wlX4$,!l6-NW+[᱉Ȧ4$-Q~72'H拕#-qJBޕj,X$p^?a ibB"&BtԠ-v#&+X@}ϵl h}G\)AF&8iYOM5 }ǭF^VzrSڿ$ʅt ѱ%6 i83%!qeu7Ww)jܩvU_'U˜=SK'b+;l'(uM>_ţU JIb $Fx%@${~B7s|lO &N Wd|Y7]ɲ=V/Nk;=m RA[#CQ֐8F7vP-2;:p;&>GqC;J#-+Et@H ɄQGs \WmlM컫}&n_ ݠ4 a/a@CM/ dW=aDЯ⒪?m2i:NpllJv(F4>ΒKH#?}pG9 9io/wda jgh[¯3_[v *q#%z8Zb!C.o>&#~@3>MR)#&!XtP68矴0U `'UKg`O0DnHH6-{A8HɘR4~5jh5a/`TڱkdjDP_Uh)$"л;?רּCfdGX@AF Yzϼ3T'P9wcFC8!%%vۃY{ a0LI+Lu5O BlCGHx}ʾR3?8p^w!d(ĆG4 _Iɚb5 F Qv?;($n,7ۿ=Afկ>{L TW??ɪ|x<J"!E m7#:D#ʝ1շRɘ@UEh[}#HOl.}uAQC+QoшG`fPK8Q%>"gرI{) HDs5dըfQWbYy0i?N.b0ΈD6\sc0o=z{'NaOZ kt!Ql)p’( W;ŒINP _>tUaK@btR9xcqϻHԹƪ8[9"?J)[?lvO@ݦGxV,Ⅴ@\Wpy?sPJqXC+4z7x욎߭1XVUU/":M UWS˯P|i#~U[>?:GB^T sh=fgNbMc+:qZvz X B?'QajTrAL7cT'm fFP i/NzCĥI ,d%?|;&lAW%Ov" ءֿPZyC#*P"8 m7U)ڳ=?3endstream endobj 101 0 obj 4165 endobj 4 0 obj <> /Contents 5 0 R >> endobj 17 0 obj <> /Contents 18 0 R >> endobj 21 0 obj <> /Contents 22 0 R >> endobj 25 0 obj <> /Contents 26 0 R >> endobj 29 0 obj <> /Contents 30 0 R >> endobj 33 0 obj <> /Contents 34 0 R >> endobj 37 0 obj <> /Contents 38 0 R >> endobj 41 0 obj <> /Contents 42 0 R >> endobj 45 0 obj <> /Contents 46 0 R >> endobj 49 0 obj <> /Contents 50 0 R >> endobj 53 0 obj <> /Contents 54 0 R >> endobj 59 0 obj <> /Contents 60 0 R >> endobj 65 0 obj <> /Contents 66 0 R >> endobj 71 0 obj <> /Contents 72 0 R >> endobj 79 0 obj <> /Contents 80 0 R >> endobj 85 0 obj <> /Contents 86 0 R >> endobj 92 0 obj <> /Contents 93 0 R >> endobj 99 0 obj <> /Contents 100 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 17 0 R 21 0 R 25 0 R 29 0 R 33 0 R 37 0 R 41 0 R 45 0 R 49 0 R 53 0 R 59 0 R 65 0 R 71 0 R 79 0 R 85 0 R 92 0 R 99 0 R ] /Count 18 >> endobj 1 0 obj <> endobj 16 0 obj <> endobj 20 0 obj <> endobj 24 0 obj <> endobj 28 0 obj <> endobj 32 0 obj <> endobj 36 0 obj <> endobj 40 0 obj <> endobj 44 0 obj <> endobj 48 0 obj <> endobj 52 0 obj <> endobj 57 0 obj <> endobj 56 0 obj <>/Length 35486>>stream xہ8rQFǀCc8f ;ξX7zU,$.@\p!OәL de_,l, l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l-t 9yU rcL`.Es<** lx`.UねpƭsIZJzR+Vsx m]<`w`.y-ؓ"({/MK^mvV\QB5uEjsPD* |ǡKV\zo8oVJ-)xPzpz vHVkv "Vpwnocҕ[݁:m|0`k`.U* b8QY8œ#.w`d7[pizaT)YµD`MS*d`}`.komjXkiINV<*/Py8  9V[[llUxU~V9VVVVVVVVVVVVVVVVVVx?W{XO.`܍|fX-)VZLm{8`́?GV9`ldLUN--.`*crja *p͘V1l{18تnlSR : hWaتV9a0*2}kVUt°Mk U bvna0ZH{̘ ]aIkE-QV4ү0luGt* qt+ []VՅ ꮤn*-`:Uw%߮0lu#wV9uaW``4&kت$lW G.]aFL[]~°ՍVA71`͒$~޹;VhU.oook 81EɪVz5ϭ6gŽs#wPF FVYdΧ6zW1*ոX۪ >9"7;:EJ(JFڛ1.U[RިU[RqӺ[T0تlU?)V7ϵը؟-?htIV6[}H -J`\#J;m2tMTT'[<[Uζt&f7rGCwE@[KV Xn*jʃ#OSC$%_Vl#l!#hcJ rpn9F*N.n%O=% .@H:w4έus5[*SتGemN{p-YCouIxX%>lZ\uwl-*DC⧰U**~m7.&ՊVGsH@sG.(Yتwݫo!rG۽[u*_+\taY>$CƞZӿG>gl{+av귉>?ްU0VԤlc,\k%O-4vZڬYC&BVjU4艸kJ5&GolO吸NUNyUf~w;Z7W0"* luo`M7..T/kZتV銜ƹn`+DU0V%-͊Cj||!VK+M /YfYFݽm"* luo`Ƽ䕞vsdr|a-O"KZ-vYq~uw~ f[ݛ'jLeK9[W,18ؘդӣb`l}```6սYV剼GfjOJ}ӫV{j rn I5zdgLq f[ݛ1*ɛ..*LjW%gOijH:g8Z7W0"* luoa鎶J5W;1Mn/Iwd#nt1ǫE&BVfG[%[~|KIHL{`чtՍs}[mY l7[ c/nov]{m2lAw>4XqM[n:u쳷Yb5x'Aj?]e="ҫI.iU7Wj6l=l4}^RMh:j_&I9{uֶu& [7=l5IVL_[vuV\dQX7sq~f'$\fT,l˻^6l#1s),Чdp'kҧlbdF?WUfEnp^uT7ήUp`,ލ0Qa}H!SL=l?B_IkS}saH:w4Ή4_gWpM*U j~eօ&VӰjت>`mCAF:w4*"]`lJVknz h3||A1BƜV2F"m";玺iRWv6VV;F;m5[MTOA-l5\6>٪;-YS5$`#aīZU0تYxVե5,h VU}/o9hV֝^/?5k҇[ [Hkt[糋WMcG+~MlյݫOХ``:U E UMN:1V]U%ZWga`:U7^j*޶l!Jm5A⎶jaUwk\5DH>qV\`\uw]/z&Kqlz|,ȞlV叟쬺[澮i! =UAyNT.On*VkVۻFX9eaUM[ [*XYVkJ(.wm[)Nm[ B[ [jq{TZV? 5yhn 6#^x+V,lu|DU큭S+jVb  .E;"ڬBV!VViwSeVUl`1gu [+zeLq =UMe؉ ڪw_|5jt:UeLq =7d t+Ey\c*s@W~g]SS띗ݽm"*Xkų}7/ҹ M VM"*XLUN:_UAfU܍E:dty[FU`7շ"[T+Y7iHE`S B[ [ ~蕭tz laUU ϲʁS []m^VЁe#*X*w)tFc)dMa°US +lu2]5aVljL7uUMUJU5e.1VO+fulo"*Xت-l榲lY|'VYP07wyk`Մ7VWa *'U!DcLjV~t ,USNX5)xS0{PA"?2[ wmTXw]jهf`:U έrZSPe5=ꚪZ GURs،h?cOEcf+D7i6խ"rV=v #27WY|$T㲰Up`}4UM$H8КV,1q%b{m|e8G[mYx VA.U*z*6pDJ$1eòq->0ukV|rfY9mz (l:&{ŮXxaI|YN z>,T)tLBM͕]ӻz|< [U@E|qY8|K7v,xeDd >}oV9nVoVaO֊k>i/Pl]}VVcm5B\[~|m5*I.jRe#m/oa~z [t昭ߠ'U;X[M:j&~Ǯ@dIBPN1*KyGtU&SJJ.`UN`w9N]ӥX-nH[mov;%U}9+l lV*&l )ՋCa׫d#}*UyS5r TAN```w6{e \XUŎW[я+nW~}[Fau VzU^ϯ_*BJ9\tXդ[5&nm+&lVm{/?ԶzUkd{Z#w5Dno_y_H)Z7WpM* ;&[l{j!$5AKޖJI;nq(A @%׃R`` `w`[詠a´*?T+-;YӴQ>j~{7yϘř 5KU_$B5ށJ_`@՘c=vxꊣmzEC mV2&SX{īiV V0[7An`Aǫ_28m#O"bvudOx;H/w'nbLq zlNZm䡶UA(A#7b-I$kEDa'QUxA*]r ǻ^]7l#++)$tz ebvf(Mg_X,Ʊ Ux)٥TM(;BSX'^GiF^5a6V;xxwOm;&XLyTՃQYYMG*f-I|AByMQիp۴NU@ [*hKt)4[6 ȏOh9kW(~&18V4ڎeDUUlU]Y!?DCxmz+l/_daLAz :b,?[LPAdPkXXa# zUۻq)T ׿GX>BuUynj&1A]V^ߓYiؿ- `&`|`J`ʿϏoeI׿j|<"cG X udzЌm"GVv:`|`J` ZS.]&TդYVX@qL1{N̼"]-KDs6K~[ni쩇&VGec +FЇ]*hY%ȧD3TգVçVG)y+֜h%kz̩ƪj+;ydqb#zp>m?8tfg8V+ `|zmu51 li*e\V~0bbЯd9 <ȧޭMb8htbU>{פkodXO``#[{o'*]+~UsR_S6G@qEJDD)jWU邭VʶliZ׷^zmVE ¶SĤuPt#6U(+\L[5[#+{lh&=);*вrfGYʤ|%Ƥ8XW4PǪ&8_۰Y Y+tn[VJ\iWyaaPNZbjt*?khj `UZtGf/[%2DVϞo]UMUjTͶڒWu (cPG2E# +qdtGf/[e_VA޶*3[HN-J {*]] (zmudZfI*Vz:`b GUMVc:T7&+yD#V[?K:-vƤIv۞VI =/iJ{DUE8wbUJ@%U5cP!sޘVϒ0ջ4[yV-i汃:tliFxr30 2VHzcǪ&PWGO-fuzbӼlتت#٪xUNjX}ֽXQFU ʀWNc.Ӽlتت#ԹYJTY>9t 2|$ȍm%^B`B׍_dX]p\lu0U%UGU~?^%LGRcluVfޚUъؼ8&A?UVīU>U%U{NVUj#"eU alUY_)'mנyP&A򀂰qVϿEQXWŕ;W[[U[5C[U4'PkxKo~m~_z/ \Y.QjIq}Bj3>VwU£laz<7'ڑ=:H-fobV1j0U%Gp[[pk^4UAbժԵ'* U? +l:z\]]'Gp3[6jm~U #vhahbV5mk%$=H4 j!V{U-i0|vPW[[MJ~L[MB-VU GVX5+[ӫU}jek5V llg}߉Y8+o( ["tib(>NPj-x?Ξ| +l:~\x8`Vʿg݉Ub{-HD+5`lq@~Ph{+ } қ=JԮ~Uhݚ`j(cW~V;TJWya+AcmjLP?Y=V՛/6q_&[Dc"Zl6 dpWUfaRa{YVC-n3$E4Ѫ!N+*Vjv"ո OZ`)LcZ,Ъk2 K5]$Ud$5vV`+Dv!U!`wbdUV^v[gK%a]u9M,%Deh^#n+Dv!ϦȄ.l8ڪxjW+*K'V5\q2}[%HzǡN$D__JGj[-_/Ͳrژt~LDO`OV =TDV,Xi ]V^ߠUA4\1ejͺCZ,\:v@[5f %=JjX[g]Y羝5pUNj)1@?5a*ZZz%z̯JT5[Uɫ.ۋ@Lt0XU~shž]5a*:Rܹj@]A%4\bU\6Wr$۪ε!Z^}4[ڼJz7bb*&_fr0]U C hvSq;p3BVȂu}JhgL|/[MYeW$)kj3 JjBb`SڥCU>U%U/U_5_֫TRPŶ: –np!(yɤ|[Sg> ʼn6Vk6j-B%ZH`J`.ЪXajmRՄw-"~U c62#7Ŋ|J""rBG>`[%d=.@v[U[Ց߷/ҪVAO(bI[Q4*hVn8mkDvqO`]VVj:|rjx@n RY*!! +0q_M+Zr$#PORĔ>)67ZuV*Z=2ߘ^J*+owb9^|e:GqfhʹgJba]VVsl51bEU* jhs>9x)k/⸣; c+FZѯP鮩~`〭:\'էpc[E.˴U͓j9=m!Cy (plꇄf?_R*fY V= .S9k$ VǜO '3Ĺ#MR4L N_gy=xNwM}x M֤sȮ``mNvgj#WcV9B$2 6mZ$VeMt6l:ܽ[m@Տja}Nd5[Cl8lZ]l㺿akVchW^=VCi)l6/+mUX-_aL_m@ LÀ+h!fSg yzQu [VA$ Z rm5~ڬ^?2F1 H LOdƜO CV>?b˼R̵#eqzN`]m58r拰UR**U\^u+Hdof@تG}(nu+h94mkVac*GV*qUr]O8W_t*jfk$^֧+l5| tYށj[lSoV1'l5SYx,FU` U,_j/mrHtuJO`Oa^uo`Ϭ7ݥlcN;hމUe(ؚT1~[Bh[} N+OU'U5Ѻ[?1/eqHMzڼ mGЇj~[ mHXF@V)*lKte5[]MV{;NyvYe׏\>تت=scM^=?+▶Hbհ' ~`j~$/ [} U%UcF.Ɵ.mU05jNΓlt2L^ЕD[2lZ￿?է[U[e[ aM uz U֊iDf w h *aaWJ$fn^℅lU l՗m[U *3|]f&eh*y+bۣ`*/V=rʬnb̺Y\l*I5-*Νle2@ALv8lu`lqH j|2;t<*|^Ks-t[%"|AF~X\2,kU@qU KrMidlSʇ:뚉Z]fb:k\% R4vUߦaV8`]0gBפk{R,[6jXr ?;CTyf/,GZt|gX*gTnPnՙaAV)c<)zuj?[_|#l8ơ8U5 (T'u[ S "j_[e N@̒ėk/VCWm%z[}lU?_V2 ZIulj[M*ju2Vdfyjj/l&1V-qr"!8V騥lj[])Wp/\k:lU lAڪxjW+ty*pN^B#'Xu#IL潭le;*a mdJUb:]鶪")L &1=޹k*~5 [ت0UA*[WP>ߨҩ|2ڂ:8o# ;7oCUNE[U[u8f*_Gv]Z5TÖTQ1& _eUTd[ϯHq)>g[U[ȉ7~(vk*j¾Ub7Ypj/[%DXǜnDȚ(^i:{Wai%jrzkPUU%UrVsC*3hյ.*[;+l5ZvgcP`{ז[ UvVVV:+iKteMT['/Z͞$R*PͿVVU^d_[֊IA``J`4ǭβUU~تmy}EA'L.;hUs)U5 _&Se:eq*jny!jx p2m%)I[j3Ԙ#mJr~b lUlU lՑ-Flg[Iq)cVbZ+o4H`":lBtDuz[uT*ibUY$NM .⏘X:[ H̥ludgv /Nj`Q& lUDsHp[uT sWUnV{ˢуSoc `իċY"[YVN.i3-R= ?ʵV8VajWl56 lg2ƫlU@JcP$l[nсؗ偤aZVsCe~f8`V=>m5?k{.Й5mΡ2?qɁoJD[@nUV U-FF*gG[U# sZu`pAV"tZV 3ӫg"UZUMS>V=jnW_OnjV23i珐bĪk~El5``dTS*1{LlYl&3U=9KYŤ>RʿWn4ɨ0jPmWURXaD`U-F6U*0c5[jV(rnxlr*2xȂ\V}OQ i.6V? h&OKōIbF.,*%8TUf+Ze?Xͮۺ!;v- 坐:uUAh[}mH:j)A4qQ^qVتѮZI?lu@تتl =+X&sMjs5kzUInJ2fO-b.g[U[}cƭ^ʷ_u%=DzDĜ}mu\-Hobu)[՚G *#s1IAVCmNL&VV)s햶ҫL ΊavSoD2g8 jkV@߰5/pK mj*Cbb{ ę a8yBl~SsV[@߰并̏V*MTXF V4c_}dA l5%ۯRh.<>#Vȭv-[تj1{'Rs9[;0iqL_x u*JlX>E9~)V&qkpHCۙgIrcXSU N9"yzZ,qӮ,l f.vh֓V5UU5V]imMˆuZ_d,:Als7>VSVb-? r Vt|ت:/[Ni &Vu5Ag-)=)(< h[ o^k5[fP+[-+S)W-ت ت'U_ģb?GĪb9~qUEdoճnm AhaT5.WqKa〭 Uw=n`7c/[=Vgt -pM|]Ӷ uSCl5|e՚i׼X:g[!)Wh,XG*lfbqb֫!է'ڪ`*[nm#[./HX@PijW,d1զ:uٱWa7c}[=734Uue8[Hgl rx}?aJ[-]?ت^Rk\J{ajgl XV\mKQ.\TW3WVIql5.`ehkuYhzjr1Va 1%8#%~ibOFvz ֱP*=J Pz *e@W$Uk\3@7UbW͝ []Z@곘nk[j՜RĪULq1=))=_wN-8rS4([ gz<|Y9kr 8bVg[U[}ª$JWe!zr];is[)ɺ7yLoF(dH49U7Kj#ݤt8 []تcSN~b$/#J9` yKZUb3Nٷb~}mmncej%s1 U%j VtRP˖8iM{юRb2FMfJuANuG[}Mn#bīۉ# luM`J`V t쵺깅9 qV&ǃm$Ȕ8]-qy:jiP̋^ZLU[UY?Q*XSU:`dJLz6xuPM13!JCW?$KB5*>2/ `Kfd#{zJW43E K~l1W:h; h5`/EyMfb-L[ r6糊ʀ*¹뺾Ŧ5K3F\O=r]tVa;WU!JlTh{$Ü;+[] تت#G qa~ֻ)SIb5XjЕXp [#©R+sb21 [aj=z,o_j3zGKlU lՋM^/%mx̝WeYbZzo&AT)7eT_zhx^tԤKfy}7MU]-Vy<(l58`UVal' YvVK6'Ws:a8ĭdVqi;`P#[f}U]{p~G$s[mVcjȭVU h=9UcѢBXsJ {k$A&0FGז}W&{p\US8z'`}X4Vbr*kAzℒqv$>B1IXA*y=s 4lv []تfRj0qQ~#[ )e|͇8wuebcO[UVC "tU>bSݳ8 ]HV'[U[}~,(] K2 e+j1FV/STC "VixվUMBVVӨqJ[g;V2]D6>>J\ ]%Q7&*_ !U%abhTV2/^Cs[*N;ZUPt*bW!icz[ تjm4*Qg&j75_)K '[Ck@+z8As4 $G\Jǖ9_ U"~ס:تت;oDLj' J[ (}l'Θ,v3 AVռcMY$~oMwp޶ژ< :تت/GNoҥ)SN[̾R,k!f5eS蔜ge$yXBw7hsyvzO`iS&?U5hh2 s} ^1fA'O]XVՙ"U>Khq[ "1C lTbz'Zl*p[}/| e|:͠50[="Wz*=xUjP [H|dZFgj';xM Dl_Ye??)fM[{㩲V$뚊dɖ=8W()3C[D8Z`[YJ՛bhWj@«°Vw1Or[= CU5zr'[ ڛ*I뚊ikk͇Z)xa^_VUYXj"`&4m5՚/Wp;[JmT9V,c)VV q"|"Z\Io(_.1]vت~o'4KU=+lom~ZH}?U jזųKP*-F>]m>^r]VSWlV#y*f/[m*0[F|T5~[դg[+V^9Ѿ+ҷGy*|{UhI9y$'* lxOb{BO~D[7@vڽa7jGOcC[ 2X.m$SF2$Vs.=*dh[M*Z]e^cxlհ ~f]El5`8կ~cdD[Curb8SJljX}iLFӪUe'w` c d}UꗲU[}[تc_UV m*z|{ŏ1жdJM:Q**{T`*>?[%ōV*eSpql*Q4تm(Y9dEXӧN*oTM`*>ZhX [ujAŖjLqG-K.w*be}ӧ:.V[U[}"NJX 0֕maz+oۛwhr[]GUz/1f Վ{P%pCIm|\lu.U%'k'tb*.{`>nz_{eyÂc2˶ζyJAURf=MiPU U%'aMU x[-?VkK`X Y&ql&HN=lU~R[N{(D mZ5Jlv\М#s-/VKRxH=V4=lEӕ%{ DYÙ*>^zn%V9Umg]Wk'dD{/&n!L)#VWUNrT1m4cI>D`J`ODl^W1VuUzVWc<V{}bt΄lu,ٶTjY]W`7:u{.C *iUs[=ItքFyV^&e81% [V9 z3ĶZosMι?F~걑R󘕤QYVyb4SsjΓbݽ l՗o֮l5O r[-&A%myk+#z[-VXh`GڪvQb[T[Db2y~զ#lu3`gIIHᤰUdO8N#3 @j%WS>N9 z't  70da[?kj-ZhMUͥ9X lģzjll3O9IPoT ]j^=`֮8o*'Aqyj3H*tOlgDAOִվITmU:8VBXal5YaY3r[}ߒQŞ[5iįaoqሉ3wRZHβfI=T7 [հ&IӼ'SnUwg$^4Jccm lKX `%7Sy [ ʩ *oUn0V+#zniN16D1EV=Z;=Vf4Bbu ^º]RO]V㛛IklOjgتj`V;z\dxꩪj[5iӾk=dm<#^ jҁ9?O{)MgYFoŻV5#0 lj` k:#Ǵ½U_{"[8 l]]x鶪+GzStSXN=*yVV)yo[mLv)l^0|-'N]NͣjUZR/zmU U%Շ[z4ĺ/k_K8<]' dSmc/2Vz[lU llU°UjyUAӥֱ3%W()|5|ϝ: V[U[}(J[5_cZLH^W 0V jv&ӧ`[U[}([U.[ej!~*ul7։#lWaj^,e&,SAUCF, lU lV7#pGiggO?7M~9Ns]V_$5GgaΠNV5VVJkV#ʯ6'f%~). `O!n4:}UWr&{D"Vv3LԒ Օ*> t$>l>^ӛK}yra&V :~k%Hb^[e1{*SUlum`J`Vʬ6I*=RVTsjYߞ ꋛΚTQȒy@ AVVl?0/Y31bW_j;Y/=9i^_ga3Biy,>a?O{cmU6,U%Շ·1*nK_j)Ϯiy3cZYV_$0|+lU;Sb)[vv]%/VwGlIŷlrmIq_O`s mU9u>SJ^XVzr"7%"VLX ;R ?U ~m\WQSnz2Vj]jyZ򉹾?IqkO` 4SUy5z9bſt2H/Ufu+ɛcZjNr|1 μ ijA{ckF'8rz[ ۪rem_Q& Y֓,ӊ({Y* [mӚx6l&Sefat[U"շڏ%c=aϣlypI|z[M`&W]5?f?`0@q*V!1ͲbfLytwC5؊hb+Bت3myTWyqId~I)(*X 2P`<ocUnU$SUVMZ/2Vi*g,[=ׁøUo`ʞV'ƒbSvuZ7a [ꏛ 7Weep/1VջqaΧ̵n\kGVkߋYc+M14 ZʤnjE. 5Y?V`jOϫUJsŞ4SW [D΍ja&l[꿩Jheq>1VO/T[UrB?N=N`..ñU Us>p2򈟇Q̀J[-&S'j^R<_i]`jgLyn lժ.l6k"CaܨHX٪L~a*kl:OVŚoBkLSO`VNXahUfN6ѫŘO_=e>yb ڜD5V)b[M`8'e@[ğGq\mU)<ྒ28Pɼ$rҟ8{u+ac*Tlu$LU''تتs6CۥEވ>Y4MɌiHsmUP9]*)DšV lU lU lV`V뱕J&X%}DNZ)ʷVdꂶN˛zǪ^〭**>z*FڶTIδ![ I%$>zhvW[L]VkjOܪتsYV`V* UIfX~1*V`'SlAX[q U=U%[mF[V.30ך,ZJ(vz=qPߏչVV lmz\@רdb^@3Tgb&*OϲW9Tt`J`υoA${j1G0y2q,f* [jayfSm5X=as*>j3`s͠^} Շ<$/{[5ofS$j47:تs*8Y0lu&l5,FZ%>yu50ت V z=nZ\[eKuBj2luwletGKV^zVNIǹpX=*6je7r}.LU<*:4r>M*Z{)ztfl8"l,h{mUzU4aVC mU6ٟH6eWkeVCb)l*lՕ6VkV;*M ,ʾm/[lw@;ȭz,[eןnYlE0~HޘV{4ʂKłJLj.8=Mk؀yjzi@`O'T?&(1Ay.rW4`&6~j;Ϳl?SOl/+lufoaOgk̳j}(?V9Y13_:,oJa}TU&wU[U[}4ڪtzW&UO-T2jsV{oI7W**>ڪ&ifi׬g2X-ldΒ~u}**>[,̱Ugq:'&aY[lbuo[,zAت@UU U{[6ox9QGPួ)ϼ P&w^zјV"Mh~eaլKl aVSe[}4{YgmUáV=24TAzmU.UJ@P̔ү1@ͫVMȥX,G[ [uezʝi7^ctSٮu[}^AaWUT_Sl5 W ȥxZ:>ƙk Vmq3 1VD2jץJJ^U'*QUdz !OxV Ky _m?qޞ?6&JhEnu5m5)?Mj Z}:l5O&+x$luV4A?_=>_hSMbj^+~ [H?CӷUf6%[NU~+U~+asd6Q}*_ZumV맞0?i^bnj3d:*I*x3~,*Fyd k/~XF%MsLٷ<>1e٪`QF DZm5OO{[5:7(tQ^.D kت2Ytʸ@-N|3>`0fQl5/?5`F0G2$oL9Q4<2l4&dyb3.YlP1c&lvџc&o'2d_[TWVs:1yxzaJ1Dh T2T$S3fӲNUzm{iVKȰU`J`FoUXa],eJ^C,J| =tf=7* xϼǭiZl%;3jilتV%oe[%V ܧxPSzЙuk<5o"] Ux%[O-"fIZqY jlU l D[ =rL+&JtĈO~NuI}=4z'ۙZ5%tc^WD8ރꁭ*>VimW%U WҙǿI.~.U|lK&KPl5_6p\U"jlU lm5D@[zP6ӟ2 >ħRj>w#魬]~ +SLdֺ []تӹ:dpzO;} ˨̅#ht+wʌiɬ)%O*Xd^U[U[}:L%SDdKQM"mfB05 ~@ l[=9] [tf٪,ٴfb8fTT!UNgzCeĎu)]^Q'Jb6#7 lU lj>dϝ6'i>(VKI^#^l]WV woUSc޶j'沞G VuӢէyd_yPhIIDrb2)ꅓBdl(U|o.C 0_PWj|Y' " lmTVf{Cxb?VV*5[Nӆn$۝DnZ+k]#ִ[8bL}+0דv_:j^l#5VVV,KD[ &eDVTxׇ5T;j).C 7mUD{sN$NzK[ 0nxabq#1i]9]dŘ.83m#Rۻ4šتfiZ;ym˅EXVL*fYq(mU9{4fX\Pzi&l\UR*FfFX$~.5JeWmaW[7_+luzm55@a`2[5ԋ7*3uWi ^lZCj'xf񙻂pevff2KUbMk sz7dl%@OMg4'0uo[WF^ډF(Hu 'MiydVͱvNXf-QWkO蝭[z7z=w'~Dn_n|oغ#+w2ampV[}F]=)U+`J`7k+fqDIsJht]b%ړ>[z ][ك}':0mۊEsZ[U[}:2]g5Cs"Yԟx^oYMFཟZSծ>{Z &}>jlU ll6($O~gZXCeDPmA1=낽c6~gU55O+ӿqXh U%U aFR逶a1*6oeBغ5dۊη|}?v]bXh[uy9Aٞ7מ}&VVA7o]\=DpzI}Yn^&pfehd*|*:lQmΞw=b'VA7ʡ#OJ:0@.u[W!fOì$4{̴3:Fjaŭ~=*Wp{  I%UЍ[;ڨ<wUgj:9?J}mvohV%'(;Y{~`cY= QuGOfcr!D3sZw']g?zK^iEOmv'y{jso:՟fG}* I%U0} ŃxstD qWF[w焩;DVMӶUm_+oèϼ~U1#论(?W1Vt}W܉ Ns͉߁jwiWM2\X/IIM۪Qe},?^[-ޖccPi( l BO@g n)2t8]{zq4mOPjzyfc>_SO`ȥ__IWդ0l,Dwďu7L!c?[Ş2 't4?{|Jꉉv}1>샦bp'?0`tM`8maY0{.0WWw ^lF5~;GK3~1Jt\*>'6?/VGcl1ZeV6izVفMݝ/|>V͉{nh>J<LJ[m'dwQI^pb[MÙɲV$߹=&061v6}ωXjVcj{7?֝sajA!lV=sq~ l} ˿!ɏTl=zA+Ͷ4޺ODjubDgF :!-E`E&ȭ07W1!l6ݏO>h ;`Oj\;*oߺӇプǯ]5s!(1P|u)#u\ְ!~N2݃Z gx;t^͞>}/~<X ؍J` M']q&qpNV\q$lR sϏqw'U;RPs`J``K M*ښؙ~7 +Dk}sMf͞QU=Sc>]?Z9yR7Q lǤ~U1WYxɺ)+>h"uuIkwJV~i?tnk:`[=Ds8]m)ݨ F&^9L/)b|:OM}vw&񙅙{_*8N 88R7`Vhդv 7 >] g":`5=+XH:řbnNnwGnM"wU;;p௦ &\jn"N @s&z(;`4gJݰ9f?lwK}J7t|T-_wL`J``8=#/oaUbj9/x4i;ot ?Y|`*`,ssvhu^)L&{~ɽٚ4qs'$DݚVw;P lӳB0%o[GAܼV< U h[ۢߌ)V{oi*ت؁J``4w]f-?-f Ǯ^Ta{O9ocmifc lbb+[~rzV6W-1R;;=O] >io<_eeiT9eD_kXc#ϮV} OwfhMbLm¼VP~f{K<|ǒ`8 []y[לtU%ysmهaOwê NafLOeO0cuU'?ʿCGQzkٹ$@||w0J1N8'smV*gޝ5_s|g1ij 4D+)jZ'<zW\m5[>l%d54WM>ZYne=] .ۺឩvj~Ml5 숉-Ϳl0z,9i[9H~OM8|3>nA|~ϧ͉;Kˎ8VbUv"ymǻyyzLwUI %qD 2Td[p=`Yj?xj V5q,;#qb+J73Įpd6[ ./[wOX q -)SܸUpsl-xO -PZU>J&v$>G*YV-|褗9]o75$G[7glQ?C\]%)yRsG4#~YO[|Tz+QsT[7 .nq#~qW\%*>u'U@<x_فbJpVOmn#F3C+"N~g ՂHtx|XfLgm {v;P l{gse,>C\31I7j+tO:0FKS1ص# Vx" #3WWO팸9Q+;MX`tCw/ `a0As] eeW7vtOӋTtM%>t V3$/ 4줛%18ID&CRP~/([Oq&%,HI+?x؟i R/um0 Hnrf`$K5ejOKUS$|0Ť fXٟp;@{WḼ5xM|i#"&W?O"ln$z*mʦdO9Neaہ,rLɀs8o}$M#~79=`c[ *MWbsu"<@VlU=lNmŗ|wjkX ]9 ۇŜ41W)dj%􃿭)d`t Lhc$)aD.z2V-w9ЍX-w-#>d-8>d'Z@[ݹ#\ˌՍ [!vMv*-0뎱 ̲ >Hp=07rj% Iv&]*1q`zs=mՍmu\s?L Ղ.{3kB޺oxN6wXg''&@D߄ը*[.o ;1eB>w5'g|S3ɰN6W [`AmlJ|&zJtc1N6[`Am`'fV㗮ǂVn7>*o0Yk.'Ŕꅡ/fO-l3^g1ڭ_[iW(ZOhO7!fYg Mj*!W[z r*<3ͽJ=jKHln>ouq|iOZrV{W_!cUݽx:*>BYp1*==gUHYiUr𴺤xMiNY[_Z-딞O笷}涱KzQ."W!gVT 7usVo/"ud7 $pZ!gz'>*@6w*!޺T8Adw 7ė@O0 1zb9$=hrvKΣ/􆧜g ?_HF`%.8?j~շ-blt`zuXg]^I4i#ꖴI@tjǜhlun<>/;nVD7 qCJ.y(4J")spW"JnZ"'z p#fZ λRKSFVsq/(7ܣ;t; jŹ*VI@^FuHr^+Q91WY`< p#fZÿSTj sLXg˹8TRc;Xg9è scIvSWKh6^ݨ>7BQnJOܐVRgn\$ilʬ LLwsT zRr8Fu LLm$}mV)p9E]Rf"qXs`V qIi,@O*@nR< < <{YϤI%qֵL`b @ϤpiH(Sr8ɬ90+i RKZ .iUVKZ .iUVKZ .iUVKZ .iUVKZ .iUVKZ .iUVKZ .iT endstream endobj 58 0 obj <> endobj 63 0 obj <> endobj 62 0 obj <>/Length 35858>>stream xۙ8n| F]l Fn1GnF-@{G~@"p50"0NA_p7*p l [~V_`/U* l [~V_`/U* l [~V_`/U* l [~V_`/UnȷoʍοWWv2Kw<*74.8!.`ܐ93**Unl[sV!Uo`[PƭNcԹmSO5[`d'Wkq{.(7w5nli_^)YƾƵ)_m|z[U퓡Ŗ%= g[ukU(_X/P~I8*7d pVyIlmlp"UnH?5ɳa=A7[e쐡;*7D2P:[mUi[swTnnl"q;bz$uߑ[Uywp'`la*7dhQC5v}3{KS1(* mpC~6+D] pSz°ajޑ8 _ {z2evJzBƐ@INj]ĶU+kvBx,UVV[[l lpUx,U* l [~V_`/U* l [~V_`/U* [)ZxOX*ViIj2XSVx CLjZsjXSV9Ĥi}$ک  kX,<*2?nmӇr#l3`$MmHVҔpj X, lГU&`*Ka` `XAN(M+z`KVUBj'U8ԏPV[D,[`sJiUI,]PPV[@*x4C7&تJCT l< ij lC,`T8[$k0nYHU  qCmrnnʤNroBB"p.Up 7mreVp$@Ub`S!l4u4j+oJahn'9"  l8bv(NVn:U9V[M4qQXz`` iyoNVyӍZ 4mB=9ڢZ  Y3)/JϛV[ˍܪ[FH۷wﲍ>4 d[t[-֭zNV0t^6ZOLkʋo}7]%>V[%)UI$ Á*s>)/ʕ6)lծ~"V#,a<ت2j+id[PΖʔ=tĨXnlUqm>n7z޸e!Z V7?E\o Xu-z/t[%KՍM C,ʹQn?U[(dvvԏPV[Nҩ`xj lUC lÏPV[*ytJl `=Ueq2lIC.9ڟp_X쀭꓎[-7MOg&تJ7T 'b% -:+P1 S%Q>|20dv[ZQg.PiIhmZoV[ Au$]HP`7u+ Y`oqqnҏ|SbaVl7ug@مy0pǭ:ˆ8H:]E,,<SpnèW9ws$V[ ?l!ZQ <8c#Xp3`O,[`0ϺV[!FuMu$hCࡱpX,8SXit76( -[*7[-C:oЭGVQ jOC`!էհp0dԩ]vJBy^*7G,l4V [>]JϛVŲ-è'jlU)JDlwVO`|HaWjUR1əi*o$Ĝvug5V[/ [eG )_ @ lU{*[bϓ.szk5U?lucJ/( ya'U}(fI/V;ge;jSlU%I~G- 4$V[>P'm ZbSY"*%:Rp*luq\{s[T[>c [8 [i`L\,v͵weza'U}()Zg[Ͷ O[l5ΰ!-ޤ"ܨ.V* lU*/ʏ.Q _SVk~pmO*|xvVc lu`8 P3.[99ϭՆ'UܻڇDžP<ɿwnblU.Uت s;|:n2[Ͷ~_{w$;A[+7IcۉF[V3mM,O03Y5u:oVmVBb~hKt`T>j_tlRF?0l:ҏRϼWPl.l jٖa*iVɴjdٖb!F]}\֗kX-lꃸlfIb[!d"T*vZxg)R 4~@UpW`D[J.hBV,w ]B,,-'gj}@ [}mH9>V|9 pW[-WT>=rJVتulF*p lA8շQ /h_D$VCmZzz(?#*p lAlՁx-9վjNg$ٽ,Jy-ezVO`bNNl*}/lϿlg`Ր(V\, G>luY;r+amS!I[XySUlU!|q*Pn4p*p l _UNRwݔ!T54mRnlU\8ㄭPj‡;Z]+i*#Va,lu}yŐjHT @ت 7)7<..[Vxa-U`-Tyjb5r}w[՞ؕ?=D%[exa-U`5BlQ˻̛ߪ>>^ӷaV`!;YuVl]p*p l OwjTG֤o˿ecJ7(sejls? <{ݝ,:+P%UV]m5ҩ.zKJ̞jv 81.vaT>{تsQ/P@U`bORO7)FY;.pq'Q* lYjTC7ՎHvORju{ FGu :+[ex[tkeOتQ,[U0<;Q8ՖL,KQ^hէj@ѧGdɷ{Kq** ~VӇjռlmV=]j5H,qtb[[[XfD=7ĈSڪfm5ЄiZLYz:j YV[QJ _j|UO[av!+-!(zqe[l5ܪت{m/7,+JI׺ciaj j^RnlU\Mm faVyoV7~凑mVYvp{5EO)bUV`SVj,gCma]e >O+w?JVBge27qEopتt\-*lu'}U-7uY[zm-'=VHSZ-V?om%%a@DfK_Qlu*up[WT5,ۿrWD V_ʶ/$I!V[2k6s'[}oZxQNl&o\)Z)It{c$@U`\mZ fȭ.ZabWYjmglU/Z/VCVS!@j'hA+ QjFx.n8V4tjOneC v^Ͷso'NraBβ>А[]#}8ۄg_IcB'ZV +.[}&Vl)􇆄%sV{[mz%dhGUc:߻~Ves ũ~.d!l"6B z4{Uʘ* ~qo[%fOjOrsZ,?լ|_`ª!p`0@[2 V/nfD=QՔpj g[)ۄ0d٨l تJluV* V?ZS1]X!Soce)rxB(;jKO7ۂJ /eC0)UmVi/4JPS)gX`YͰU U!Uex!J bIb]QZ˶x0d}TXbcսVV*%{uVy!*/[ !U U!U53's?>V۳-#gTfl تت*i{ju?&VQթv걶 ̶Pꁭ*?تت*[멤vJ[MwE_uVU CG8lHWتix[[[_{si:`놴 :X=`kaB`B`{(m1e[:VtbVv l:5Q-{Xa8TUlUlu?3(#j9 DeW8V➹,c4uEscU9 []Q2_nD[e4J;=$.لZ[*ٖw7G6')6V5e>0VbIV7~m2\vbLEnV)H2J,czͶXNGت幸ZlV :uj &ڍmNvlS-gjBoscUw`Tl\j%`X-H68wjwEt[ u0y+D~mU&"ٟvuUarfm5qJiU{^c^V]|2 'P{)TU5^Gj@Y?rJ[B4m;Gv%*U9έIV)J~ifʼny_:*%v( T 9Vcꔞ|5%{QS~uqznkm~rOډj:*/vZVeVqtNjj᫰*חnzP`΃sVg[Z`{ /շjIg;UUQbcفڇC؉.^%{m\[ݱVVjE=Ƌ2-/WP$#g[U(j驝T/ZF-%pole*تت*v6$+\`-Ute٪5 Wتت*ak/ilmTDXo{?u:pm/=V?;jlZc) [[[pvܸ:?;U=V]jη/9[ѫrP)ne`naȵتت6ZO[ܳ~.NGjnj*lhaB!ղ|[:lUlUlu]\ҽڱl5EtO|oxl,mV!lu تت6qsi>5,O߼FmjH w˔[O \Cl ɶPjxV-J`ǬfcCmX`uXAg{[FTk nUb.§;*"x\*7#wo%Jzk屗Q%ɋ:V@VIn5]բ~FO`۸4;@xQWymŲ2W=ooE+F~gQr[IW߹Wej, [۲揤J<*fx0pXAӁzjEޱ<,׫g6HU5luX>]~L*jE/j?ᯇ*TU-[M_Z6V[1 ^v޶:L;}+-p~tfۯa^UpԺ;V Zٞ8W*E[ Uk++7vz"ׂ| [HS/a:k5=A=jjXe'V;ſw {O b:Z])U0=lQ ij$}W92[vejE69wǽA&UJWaP[PkDe1(&^5m,m1,dK۲e~e,`b$@>_>lv b&V/ZGfƹ/Ut[eϵjtubjl06Vjm+a"l8tgҋbDQ hC*[XfKj?V4lmYc 6[3VA7[mHʧ! jC2qc[f`S~ ar`B` gaYT"-~)?xxa+jY2[VVVA[}@5VdVQmܞ2{{孭rQ֜1,[lUl䬱UbI#IJĪVZ[UPa TVf&1LQI>@N"$[ ޼*vlZ-)v`B`[2Tv+(5eZ}"-jXYpf[-_ͶӔ,&_;V b(#JVUU=T5fmܞfIGI#5'WتU!UPAV Tg߇jTP"Zz[ ᴫ!Zv[-g[x*U-`B`0`s|hJ,o~Ja*zʍ_;MLI#t5$>dbU-a@Ǝ> K *Yvvz[ulը[Pk7뮶ڪ6oq4נOa*c*>kK?Aa#ѵj57ctU1a/ T j1kޛ[Xs '#;V&ǡNV/(bGdz~}4{Tư*> {y68BsxŲ-?AV K4l1ت5rT+ Plڗ$l5ЄU'O~6VUFbT7`t:[բtWQ5UF;[M_dCBmSMtRä*s> VKªjY,]+>:0j]aZl5ʡF*lոLU2+ɺw *lj_XPk2[BUVCW,lanڞت [ 5y5PU.>ߵoauتb[ #}Z۽m|)]U 3`ZGtJllcv [V|,l5퍼W;ºVC^]l-\ϱղd7odElY|{U-1TaCJQ֕_TG|M.ϤWaetOvE)0VQ![u [~Yiqej@*{T.+U%a& [퇘ʳ'jY&]MVPWXL6uN ڪ:s[&Ve]?kiI/UU2U]*Q}[d[حV[umCk)XծZI^ һ^+V ҐKXղXL[-CUiFpj[[uTle(FC!}[N?%X؀~ 'r v1تuHJ]ɎJv3mܘꇪ*[[O6~[Ʀd})ZF12 '&V;:fe ]ULiºY`jv]"}ZTWnVd[ت"U!xۮګ{\>4?U>ul'U}W)jc =FVW՘wt R1k^/تU!jUCpV S32ʱuf-VC_1 >.ihKtun cȭ*[[ en3?:̡: SǗ`sDf:Vن z[ fIV_gtU>XcgtUˉ7LE>-w][UeVdZ%ﮁ mbQUua)fԓVSTڥO]`Y]PaYnlY,O^axgs]*̃KV |ꬡJrw8m֟xt李nr{\./VˍqY墇muJjbtܭfrv{[y [p$bGL3kmMjhB߃UҐEYiJ. btU˖@F [Y9l8V3Ce\C\oCU _(oh򒬋V!‡jY&]eјjN7pAo!ѰU?V1` tcJ=ɡUFbjE2Wi-`!*ZCVoL=l IWniT(ت{UdYl:'Ʋ lBcV,JOR'_{P[-qnƸ\}~EHj4 +lU):MpkV;c* /tzի|j9궚Eoi"AjV*#DYmOW]N85lUتj\&հhZtxJn5ivTXf*j㧞a=@EFzU>CؗϵղXwzFZKWclUتGj)U ]ͥ,S:6cUC]To|;Se!q<UA3SU#B*oceTώ0vQ΁*[\[$SC⚙і TBY`lwߎUITMWyJnCReToDžlWnlUتꄭVc[IYV\o|L8VogAbU / \\|xkJ΅Kgell|)]<z`Bkme%V]*bڷR/d=uC;"V;eʍ}x_6ъqܕz C+s%-U.U!ՁUqaV]vjh(lQE-#؃A[X"v@H^=w$1|?[-Xa8lUتGj(3 6vWS6RB:gbi-V*E#ԭV?1Glu- cU]`Bh8ڙFJV?T5[MڪzBz0Cm,.νZ'O5j[*]F;vjLC2jdnvbQimsuUX.~1Qk xVu & [ o[;m_Ve*;IJ$\C~n4쥯[ {?[-թJ`a-XrgVAJX:qZV>VWV˒IZ5h(S [ <[m٢>DpٸEUPg}ߨF+P[ z1&8*l5 ɶ k8VqQZb@2rgmծQ*`V^Kl7 AX.ӫ,Z^-au~uԗtl6Tl7PTZ3l<ί՟SY*;hՃ_I(NTZoZWɻꬵ690]]`0l5}?huƦwM[[Mlu9R xE~mVtj լd/s[ SjY ]e 6'0=`Vw u h9&V*pHy='Ra}UuJUas@B%n`e Y[퇧Z])UDnoF+Z!j1[lW'lUҷjH9V˒x+lUls*y|; _U5j@{JuDX_UIHtn H׻j2*rH=:",YOJ÷%OJլ|J=V2q}hW'$lUhٛت#β֟?~^buX OۭwZeceԯXV>vuWu2Wzl5blkWVu z^By΢ޒۿ[iPC[^-f0W= BJ__W sygo9>r{\nl׮xlUتت JI27'-ޙ>.BUC2ZwT"NvxuVt W*jzt{IAqjV&]o2Nyl@nUتت SzUO?V[ՅaK45h շVT5m5-`F*=ZF|l,ٟ~ "̭ډlnuWO`^6?.sWڪDU/zl[lSpS[ .jRIb[ݢA`e7'Ub UYƬnUDŬv/nJQM2ގ~fQy0>]5mKeԜ+ {[ex}`٘iiWUFb9+r[UiT/jk"zl&a׍U`B`5ړ5$h %_#˯z (KR&}jܨ~4 Rm5ۘV V#`VV=[e' U v[ g*yQʌ[)0ҫ_;de,([U!U8ڱ#l6;`pW=H*/˩y 콱 >U\լ|\^gG>l\VVុjMX_iDeCi̿VZjV>]m[;jI zتս&zqIdJdT J/jֽIWdiTjqce,[Utj)*l j+ڏm%\c h K1:E*5A%z?[eS[o/[[g[}ZPqPHa!]QTRV5 [={<Ί}}JmM^l,xz _oֿ좾϶" Gg2<] jVV4 [=eȶQ卮 _ '*#F"ֳ}6YIz#^]0eqH_eNլd\^I%VnZت [-S[Vr.꿝Q3C]HSԪgnJjhjxc~2Ojkf/e1ت*Z*g[}F]pjhNϳrӳ+~F$[]jd粡X;[-K+j~+nZ)7[}:?:u3RUQmm7[j3`*Xɶ2knm5Zsm5۞olYǿ #Zb$@s~ [=rF[M\Ogݽ[IYn S on 0#l5ۘjtslU ھfiتS<bw.yV? N֐_|vzU02YZiYT\^[`x}`NlavHʺOdHh}nf\c?_|jzUլ|\CIT8;CQUoVVdhHc@uU ړzU UUN?I5,@e^0eVW9;eu`U `B`04ګKUzDe:եކɨyk^S卼gf㲮9լL\>Y*U1U0aAz>Tg2a]WSv m5{). gfX6OWa VV]GOեk#{[Mi 2dՉi"ZrwڲRXm5+ke|?[bUz=F% [* ,Z.UWKiD@Ix9O/$z |֦}H! nm5 LW/@[U!U0`VDZa1B<-V{Z2<Yb5 FV*nqR)叜UWWje׭fdHȭFx l4{X4?o>/l|Ӛ9g빓~z$+jqx> SVKq?[e;WV jhq.V}I݃˺ќSmUSq KVCa; C:VrO쥸\%1:V [MU5|fXuZP d*xa*nE}[TP[͊+|f;wtTU#`B``/N|G}lD*iz[=C.SUT"+θ|f!qb[ [[cj%Y  TfZl3wP1-m5@'jV .oy_(bT [[clYk.;% ? e5mCO3CQ{}޹1լpz[ ՛[[clu6Z-dy ;噱a^[x@N WDD: c% B$Qz,0]]qĶ`VV~Rn=Pޤvrc[D5Ӯ>j\ֿX組zSU"SV-qyx [GajlUlj*TV8< bDٵ;KK8VPjAM{cȀPX$r>gjR\Cm5{).wV[[Ų'WM=jVasqc9 hjVZXp?S,C8]S޷Z.(&wVr f!*l [fe٫],ΣVrV3񥏍UU ډjyXL[-÷**5=A1/;*{uQ@+pЕŲjĬNe=|Rj7 l/nmwcvղ0z5~)A0kNRXˍ?|eU. bٖl1tf[ZتiZcUتSj'Z1@XkkAx?f 5sM ]C2ߒJ[yӹbljlUl*= Y _ hitjgȟfZӝxU M\!S=l5+߷ޡ[* HmGSS+'X9rcGI[/$Cw^5]ª5 3kV<Vj lUlj4jߊ#-T2,OIͪK9SQk_llu5zXkJ$=,FLnSl5]lت* AjuK(Ky-+'0*al?[Ek5#>+]FZ'Hĩ:7`я"ۣbwޠ[*lvO CUz1% M۪ZPyf1F k\A0V1rdĤ9N@;`vVV=ryahzJjd}ZHoNxVAsZfkWea~.qlHQN 1ԏf7T ԽC jlUlGzU-U 5-oV+Z%2Vkyw4I+[RMU2v0FL4*]]0 tK`\[*fV?jlڪpHb,VUWќI$(qA ]0>:[gk:rz =k9 f4 tY1gU;`B`Ni=7$V[az4KPIf#l5-v-gwZgD0WKLˍq זe:$U8[^ˊ@j%.kU[Sx7 B0NnUELdh;Sʩr[lQU`ӽFУNRXvugJp+Z W`i4RVWrY jǬ.;K*j l#fZ6LϦʠO[-c$axQ!K2)PVHX*w{kl+>Tz +P^lg@}jV2._!U;)} V/βո,90hqcq*He}@o⟯TzV[[M5תD {[͢>}^U#*Pojl POV#F*Q~8Y`Di'[Г fRa9d_V=Œ,_@ϲ V_XݯB'vv竰]tӟerh+< T zӓ5Pjeӳƽb]WıVAʽs z[$`W;y( OKeT;ummө|6{m7jhkk4m =&LbBӅqfI_VlRYթ@ةHUc@U&w*O=8kI\M@YRX)u{06V-9VodYO`DVXX=jP^-逤.зTTUB̘5Tixe^fxe+تت_j&v2߫?370Mգ+Ima UbUUS`B`gPjGRSJa-g2rU#l5 Y=NūjjVCT{5[amm5TV.H VM Akz[%Jj$jܲ&-OݼךˆfgR`ezZPOm3Ju}z5>z5_zk[5*z$6ynIfߩ[}J'OԶ,&4jH8skҫe25oUS`B`g~$@zMm-{YT(de}:jKy2hMtvy`] eW)^-j lUl5Uh__^^gjVت59"[ҵV[o rW[Y[e$-Pb2g1U]jZ'ʆd~mv?[85UdǧWa֔UsVVa5IfUoVUlSs{fVUf>%cL/'Mj}lƤCca^**l՚jmmmcCjg}˶Wmܩ?LdYyV+t *F&ү$נm1in5o0JKe^Z#'U0VӨV%CMٞK*n?n\ҫR.ZI\^V+Sg['X)ayҫUkض.so<| |1k—-ҫ p|&SJʅuTVvjZpn'Zt`e>uJXum5Tg( [g[[\aoֲ1jU$N~j ;ataqWSUQ8uV7)_}$ծjR]` UkZ.[a 뷘T%#=۔º5OפNUQZm!mUev**l՚l[-^TM0YltuKO`FVOd2-Vb{}}{$93D8ѕ'kmUO=nZX=tUqj*Fdn5a Olm!%rD 휸MSbV܍%([UiFS_>6gƵ{ ll*٩凞z[*hx"%5%MXKnC0;:+ZeklkM{+Qׂlb fQwQ>~AfiaDOZ[[}4A(aZl"|jzy0ŕ,lfv&iZŒ//UbȂfOMP(_Uk`B`[MgbSLVk:I!*&%[.7 X%@rw2ۙ٦ꦥ^ ?*$7,^UjO}{{/.VV VkAb !;5%Q tSiU:-]8'oH3uM5a^+lتjZIJ h5٢R[xzjZ۵aN+sV1qy@M_ u\h X?;U8zjV >٧ uZPߩ&u-lT۪MwHQkKtҺ ډ|#X/ B7Q-T2S骚 [5* &;ԝ/PV2&aT|U4> ^8u6B[ޯ|YnZ08^ߟmUk`B``[&Z62M*=rZJսʾeHj59QXOjU1ʨdcMTkn:* %>딒zqŶ_ɃY*~lu`΁ +Tn aTlUIeMӖZM֖IN5ra T=?[>/~g:myЯ7f}P'U`,T.wZjH[/e Ff^!q䫢eI볳Nl~Safzتsx77uOunF=+_,jt;t+!}_^U,ZYUۛI*JϼT:تstb7[a#"U!K_T+,V +j6 oZH*8Bq0S/$ U]@^k I3 Ua $0l52_ [(lR#JCT#IU-y;KJ[eLJV g_t~"UhjRUޓeFsTӋ_ץVsR[ejY{^٢~%b*V\K^Oj7UVSڪ|^ahfU=:N d5Uj.XhK$BI;RZfn@4I,~ծZRʗ=qolu{U M1 L-V}cqʞV4Ųc Z=ZyV=_tS7v}ZOՙ.>Y[ _G^`jՀgyBVol,Ckx͵띳yj+Fy2ѝ]+VnqZX0v-FRl{%U4W_V[[|RgciksY_w@n+FH_XyʨrWքYv[5zVNGufR`3/SK?Z []lUlHNu]bj]:ϰլ:Lj VPU~9XEe@!1jqS!r+i+luU!UjY>.+d!Ы11rT;[5s*Y^՚5;)UP_SKZ2kA)dUk`B`)d\ x6VCb0c:MOU#*khS٪tTI~l7jUp* Bkkx2q7xf-40|Dj)vj5J}PF:*^TAVPF*+_s ,N[OapTZ2:up~T_5ׂzU|Xk~ӫ%Z^*h[s VS ȴՃyne*:|,Ip*-'VQAoޫN% S7f' yBHWlm4 VSݕe-vNlVym{OnIVï{سPWN1`R0i|*WV<F W6sT\o v*pGv Փ][mX\ g9.ii|f*Z&jkG):ܿxB\IVbtߩ? zkV/2U,'s[ Sn޲}] ,i+V}2E.kjP-ZeʇlBɭ3Q:X}TOb]O`nm5~-yT거ۂ-U^u_v`IbHPcN%~ZI W9b'Ւ=_մP=먟 N-[U?:]+P5 8{;)UhOYs\ ZUbI*xԛ%֩HLzVͦr߯jꌭ1A_a`IڱU# IU?NmէM]ɢj'vݣt,V(?:tcE[2B:< ֍}RV|St-bIV1JI^eJO~TVpJ:j4)IJΖgt;MLnԾl˂)fWΟz-NJU}Pjw,82ʇo`/=Fuϵ q 1Dq[4-r?ժ5kǓZ7ʈ2R:>[_8[βxY*g2_ tvA۲hjuX|0IG[ 9Jqv>lʗ`A^8? )Z24ȬZ=&MXUlݢiIiVZ󿄠flzT={"v*i}>'U?[]yb=ҫ(I֥5?rM˛h 3`M^b}[CB}[X*ݟN-iNZ$Űm=TĤUIbȵВ?r:%-fz!xs!U8ɱ3Jک(LPbAl+)"g Re!SZ-Y.Sxخz{Xl<[M7^ CST1a[ZjK~jTьTYz9-OP |B`TX܁iZTR-V:_!U876M WtKT=J֬D6+ WEUUmTн(8ep+m&oC g1xS&PF`d/15)̕vjo4Tf )T9yŲ?7x"طB`Y/4婯ZI;]O6VzFИB FsUO[!U,nZ>uj3MF~^eeokAkj|yjCTVBJ硎I^!u/.W믶"&݇ZeF4dˊM {ꅮF0*.C[]숰UfCZ$;SO~š8Ż!z։s&-;?%: eVFxVW1.vU u#Fsl[m/V={4Jg,heZ@ tqkV-֖kaDҋubݤ/ SJzU&U[= IUpK[M7^ k$29lʭV{ua'a*-RH"]2ӫn/k[Y5UuoV05oV&p,HCfe؍2hEIӫy}d+mzJfPn8<  >[jiJ)n qk4 Y3|AP-aD j.KCWӔ*?N =[0 sZ*qtqĵ DLCթҚswj;α?. otl-dZ- ҫFAO*sphK!']F 7z ,; ɨA:-V[Q՘XK|vX疋 }\ᯝtUgS`̂ѱ+v_ȮjE"Ptwcy[$cL;5& G7U*D(۷dz yšU-[zEnm54<`ڀqS?{3?Nl/Z M藷BwMOC2l*Jstx?f<ƒ9p뱰tz`VچҖÿhκB6# IV#I龧^?8|Ә:"G` l-Y-袦r![ja: Țxꅇӂb*U/dЕ-p] yb[׬Vͅ6j#Ob/B=Z pJ[ OÃ?d3ں*JC2.[=U_Ip  x6ȕuUl#w,U1Zm1v+TVJcZU5,`UW'"fU ֕W*mhQ̶.V[iO|iO-%O} iZ^WitJ-ZjP:a!UwY5ݪVnj?QIbS/74wUNu^xԜlZTbadKQ**! >ۻ%Uu }.(~bIֺbp36弽IZV_V뗅kb+-oyNp9U/=Iu2i1;*`a lmNg`.AryYy+4">bkhܧPr^OijKZ%JZ&:_>4gBCd9mzok,a,>iI쒝V{0yqx07c徂kھS=V"B>iu|GʏT[[V YhSrTW<;*13< VibUVI 4?ckzAzS4YU8Vώ%iUr}ackOLT={tGG&9Pϲ>,MÀٞQx#v*Inqq>DW&9jVפU \7uio$Z~p casj 4Ai3iZjYV+UU'UVwG>'y7_֪jf'~ÕgN.Qlt7b7gIDI3E85j-wCLU?yj>o!V&L/ Ts/sw0Ms#rAS 1Y7*Z P"}e7RU>Ά_?SBYD@g;_|o!0/I^WcOC?oSZ$+gl5*0E `UV헅,Ph=@6? OV, hU`>j 0y"O_j ]\ t;z/@*e H:0u xQ-K`~%CkG;x:ʔTL`mC.o5Ԑk*0̨!MdT{u| ~X -0|TL-0|U-0|TL-`D*&/J&3 Vb7VLS,0=E xMw+X`bcq_ Pc P%Α5-η\oQHсR`L^sy -iUXgSeiV, 0 >~H5J@tY)P+EwP *V'UXy_*@”U:jUJ@*Mj%@ epZ k}e՚ PCZ /i ٬U:jܤVGiZ 0.+Uj%@H4?I UI /iUVKZ /iUVKZ /iUVKZ /iUVKZ /iUVKZ /iUVKZ /iUV4 endstream endobj 64 0 obj <> endobj 69 0 obj <> endobj 68 0 obj <>/Length 14928>>stream x]z丱`j52,/z5Ϛ>>;!'׶4{u`ϴ/UJ:!{hMr 0䒠j`;!kԀ=v`BH=vH=\WVF=㊶AY~EgԀ/6uN`qOE͜?5s!YH+6`_ѬO!fIAWpeq_+CjxV`;a7V?*P[{>j)y,-3 lGe˜MW]b̞-xgOC+`ɂYpAɴ=ڂ=vdgh{AVptFR {hQc zgTR=Ԁ=v`ß37 {Qش} !&E>``T/Dh(I2{ˌE=Pؔ=gz{j(l{QB2{(PYbje~e|* {iB^{ P`MPΉ={`PH_W64Y_y{ P@`4,|g{e@{3Buf@r _`ci(83@ 9{]p{e@{iP-d#fdr;ڽgp+64wyKm {\C=V6`E1 =>` {ȯl&b{}  K{HϏ=l2P`4 F@{2P`4 C=hQ,F=5{(:ueC: ؃(g-6`e!ʐ@{`Н "T6 l0D(`0z*6ۃdeP6  yL2@= )6ԇ2*P`4Ԣ]bC?(C@{`PH,6`ױ`Fu'm!{d=4{)bCe{x]{u@/;^ m4l=l2P`4$Py.=e`=h#\ifbCem(F=lTul]z4b(`0 Pg{SmJy{h55{/gzEY)pJU lXd(î=lnOE[Ϩ{({`[32ņ&Wۃc0@WakF_j/2K{vL Ƃ=l=yCM"oy:e1`n`{|=ȣ4:=lMo{HC(2TUA{6aN/ {}=B<~_Qǣ#~{6RoK(,@Ћ|ǏgƙIí/:Na)FX5z1=d 7sb8= j =$ņ@2= j =z;ۃB:3@  {˙y=\Ti7uyK@ {0s{!V =p#ʎc!:O=j =b=rvUa0CێQ!V =pd?Ô=pC]`B{`=+eiϏ= j =Yt'L퐰Q!,=؃v$CX`+RH =V`=,?e {؝M! e!!,a,oo( =a{vgU{o#2[=z𩿃v٨!,adw{2[=]܀=Ԁ=r=pݙPe"{=r=pݙ2Pe {nڃ |``0awfWo(W]9s!=8r=pݙPŭ=^u=i[H`8La7EfQ[2ɘk${({`>K/ޠһ}ALŕ=&i)bvǭ=|]{8dh=d,V8`88}+iVSN\ C\=HgAB:[|߀=f`0}3PwVp}D̫:IE=LU6___фg,k)L4m`G`lşhçҙ>!B X`kFu,t[{u(@؃=v9=9O1=`#{xR=ߓVp5k ˀ=1=zCAQRir u q=2`pBc[R>R172OEKEm TU\Jjp?8Vc,Lu )KPك6Ҽ^ᩥppG>u>E~.YqZ==Q+χۀ2=?)HL{D ZTpvퟯn^{7 |C̠=f_{-W2nLuE"oC+cac̺=dä3M.CV` =Dd1؃@MBp=k̩Χ$k 8LZuh.~bG!O{W3E_,A޾qp@D{hu=gmf -=X  ΘUio )6)<2~-=!`5:ۨt^6<^K,'0<05z<; A Fo(+{P{hKC{HR,Du#aXtSRfzíy]iB\cuR=\,om'3ϊKFgo 6!4gFt2s1j4@n՗,hi 0Ee-p1X-C:Ah¾[{(ZCipCs+2oGiyxf@ī=gZx0N~{70/cCɋ!=z==VtѺBh7_߱SϢ @!ḇ2 fVX=`F{xrj{Pm(O=M}n``qnro8t=J_{[{8d⎭d ɿ=γCM,؃1؃;,ṅL;6?p{Ny5ᘶ` ?|X{#X===tih[{ЪAY & BEUjbazۃV!C:!PpC?c<'^><L g-@絇={ [=eC졕:gM&Е-cWymW5W8I`{k؃vf|C(XL̢<і3M,>42_8RKCsu8QaE{^Nf5`^{/tnK#OCMPz5G=K{Ljs GUi@2!J[?nbԎ=HnLpЋ̢jTb{HdxH Gh=c3u8$aEy{=Cy'm{=|>vZ&`ڢ2V___c=ӹMzHl< A`Hr{^NnuƒY3V0Y2=T3#=RT=Ф=ϐt{s"/ 2SSSQ?M=5#kǂX7A:܎TG{B?{>ʝCd3뺇" n^j!(BI=vxO{vy*0 ڃez{hO&ߧZV/S])buAZ^O^xRؾ]ūfl=&z{XR[5s)^=C/f WpOO?py3{ (<8vV='ʝFhU uv0zԌFRrj{P:K aa,ОW]C& $vx絇Tg{3åy.Ӹ, ^f3 #![68 eOMN^yԲI!s{Y I8a eI#>ímd){ȯQ=5x#or=ՑM졟:`+`ie dY{qWYi{D$K zݏ:tWjxDd;˩u8QK ={0{pǟ{ufg{hABvĒX= oZ%؃;|=K'xÄA4.]`` ^ \wI-ɴW[Z]Rc؃1؃;r;oL)i[^fY%3:>K`d+Kw~geQ9w~=c3`B@[K{>ؒE3-l+V`p5s]﹭=F䕲]xxm&L!V`Ȥ=Ⱥdv@؃guw|m󔒲wi ^ cd+KwDp>vxjx3CPeg{$΋gz0z=c{(,h$~v{,m~+eSy^{ 沇|ɡI`k){ Q0~wb-\=:CrⱕqdC=CLRbpXBb8 =`d=̊7{x>;=Seγ=بCdf=|&^K90C o,iԎ=xCl~A a ayMfI#>|xnCM:!V!= 9{PIDp:w{{0{AuCS|==!pK` MA;S0{+,Y9"tWg&P{b{8ʷ`Jj&/]4tѮtkC {Ȁ=Pi\8*=c ƷhH}s D1wFSo# Q`eU{l"fL=%?P{maxz`APٽ_Dgi6af;)_= a7Yl($APyVD}Q ɇ `Ì$=A^~]ՑgaCWGOmyk,&؃ \XO!Jv9g"5UEi/v U.w"3o !b{xL=!=Hn!SlA3XCDᏧ.'* ף,zj:|eX`zqJDzO 9gx`p#c 'HmmᤉC\3bz+gC2[NC*AV=Y< \lsAKSK"]21Ŋ+M!U,#/rbC?p՝y%_0\ k\`ψ#}tc`8wLa{5m! Y:čZĘ|Pc`Nj.еvv"ayWcOfϾ:48{h~:bu5o_ԭYg%b:ft`ƹ=.`?Xu89b{hQڮu+;ŮV~D|}'} j .ݟ9{,K W|̳Qu+CrW*>5dy,i}!ulCiv0] :+am,ۃ=8§=ߕc&N:H\IS*u D=hm=lx AU/j}r:̢!p[>pB:9b[C4m,`$c3O8 #ODA 8xHq SJ=vO{^< 򖇜vgAb`EDumR/woZ7{(p[蔽c$1*Eh-$d$ ?(&GqC>p2a;Dny<=E=t>$a7#l:zɆ3=Oe/`pWTk)³:@ *{58?Sp #ԍS)=4_&=Oe/٨X(Ej__f3p=Ihbk^C`PpDrp=[hq Wp& =z=jsѾ|vxPv-:`f9wjhàˀ=lZ]=R4Ь\<:\wl?:x{G8h)vFRhbpD~>!{N`1p|vՒkK:\V{GTT՚NLb:\9Kz`4Jpy!cg)"TPo`+\:X#CuBـ)o`XK?0)J:{<+EC{YGIëq?b%u8zbo:,qRz`"Dz<"٨)9R#WQF0Zrn}JmX$``BިR w [<{n)~lu>=p͑>i`K{Ţ!uD)c/ڃ=lU)ƪC0>j=S8 v{i`{c?`,:(3f!=nw9J0$0/'s̲@!"R x_ @u}j/gr2`v yNJ߮ߑ `v P3U_{DpyM>wj+csvZ >wcU0;d=<!1ۂ=L{x΃ `2vv0Nf.`>,89>I{O{i=  {@'N\kNЁ=@AOX@, B)`=@p>~^x%L=z<:& kS5+4 j-zlhy6S*B(S揗 Nh@= H hB+~ՑU.p=@ !Z>ݙ)ٱ)@:Ё=t`{@:Ё=t`{@:Ё=t`{@:Ё=t`\ endstream endobj 70 0 obj <> endobj 77 0 obj <> endobj 74 0 obj <>/Length 20470>>stream xMz庑vٯ;q3 7tߞMJa' " ߿}j`_`5/X V}j`_`5/X V}j`_`5/X V}j`_p&?~(7 -CYNI鼳,w7 /8TN1 X dfІg ٭=A`_p&q_l#>{N{-VRiL;5~r{]vgmMtvGZ3IglUjV ?I ΤGTMڂ }iɉ-&i^St/ޚg ng"쭶 3v[-v'A[W^>3;mг+oDNvouTxо3^f}g^;ط; LF,T3-}ݓo}c%}/8l 8Wے$ͣ_P ~A ΤkmbR8&mpپݶ웝7L"t.7dVme5H:*Vx.yUeʚqwVg}|}S`bBZeXn9LMK*q!<pt˳+4`b(`_#_0fy}v̳SLL n ޱ1:PW{*ac7Eg~Ƥ?NN `bpK`G3,6Ao1o-9=[~Ud:r;m\i4&}/6Hc$/f["}jW\UB)}Uw&lL . Jzu_bP=*%)͡=o{lս5yRAt8@˭M} X>žzcL`DN5[Ͷd_ȾgEc0\n|AqDϳc=1`eGN!00}]}_8kUImMYla|fs?$`$fR~F8`_`Oê$,Ýkj"T<6(ǛD؀}>%s[s!+o=mSx|cbV} JbP(-} 1MhoLV`_pW`+̾u؝k&* c M6LX>Lէw996`+1۾e0ϵK?4PǒJᾩiyU][jm_F¾{1^y5>?=`dqfm|x Ǖ~fSo1b*bBaH؀}/;޾%GO!Tsɼ+?K:*lI?_ӾX<0fFU>k>gDnUO0߾#M\϶Q=j {f7}-Fh Cb2~}qf!Y"cMߗ9W_~h}ݲM}4]O+<ѾoK?7w{O.`_miK,'1&5|/{*ڷp+~[ą%V8wë/o=D{c<&UfRD/52?.o7}19f}7֐d38;MbU×ٷgG]¾X%a_PY-_ڬ-E)Z^m {bxyiS55L`'}0]!b}!rIjr$V#6BaM{b}A W^jtI7u}v,+y/fE5fC-[xddto(b/"M}Hm=[ ^meKJV3g/w x}t}-_ȾٮX۷\VsUt4=6U`/gl/O}Ir`mYZXctK, ktW,_ѾY}+o0,o >Uþw:=Xu.t柵KOMd}WSְ/#1UvFH|x6J^I%|6cso=pO?^atx}Wq<,Mr?J@79ְWrȋ}3 g et/[sZ8tU`_ Zv$bV{eL`8ƴ7jLXbPHS;ؗjlCG(0j;j[U<!i]Ixef=-%jrFHC WG˲eOh4 <+TUe=մMw/Mr}`V8׾o鰏=6Gua#o%kD%:򀖆wo k$S =ᥣ_h@ٳF12~MIJؾٽm6 =}!C7bߩigmMǶ&o'a VkRӡ0r &kY=]Դ?Yd&+tUgj0{OF+x0`qNz vyȾe>03G*_Idw5 }]ϻ N6*/}#ͯ(}Ӱn-[i[ۊ}Mw} nIJ~l59:D^m%Mrץ뿕cj>žPӾ鏡}Q+>þ$L5xp{cx1c_t_! kWU469幩0~Xeγo=vyξ;0%aqk4ޫjGj_vOL;4%mce% (Z@0Ō27 eҽ˫No[]`Kʏ^2R2ȩٶz_ӂRYgv@Ue, 0- Xxϧцy Ӎ+EfKk߮z48ڑ+h_K¾-aqH;CQ٭ʟ9.?WZeZ{V}[י}B]erY }-=̻~q} k|$Lyat9B|(uOBؘacm ˜,/} 6 /zCw,X`sO߷[Lo_ '2tUڿCA2o v`j5}þTɍVF«jF^!~ilW%[{d8˾Pv1}* S}To$ceV;Wg1dyh|5Y"MBa=^MjElϗ}`_z^mv-)ZmBwA^2ᶀ5ia}]`_ޖkط^̳Ch8<w4%yذt.-CKvЗ `2ׯ`OQ5ױ(|M/ -nowGVW^tz Lj-~ox`_Lo]d Nj^yz<5m./|!k:zNUkw<*r7maߦziؾY'łǂ'gGr0M楻5cU}q=Ip}ߕ/F?YƌW%KZ%}A7ykaZ÷kVDe֑Nil)J[GsT)IݷUt/}oپ*pxٗ5$°W i5Q[{MQcþgg}{[ W\hu )Fs1[bƆi0 וLw-XJnXuKspO_fJ<|{nL먌4e͌D|a9<|'JP:- ^ QZYrj]vsq>n;TIS$EΘl{PqJkv/16Lô}UoKzgaP)n [S8\m?JnjwyPi_jOo+ޔ"fgt|kbC./s?5knՍYd*_l0k'|v-f?^m^#QtW~ . ?,Y~<:xľiL(36\ -;T$VFw g5E8{}U]\r%> , .ah< 1 Xwa>,m[kq+m_:a߫}3\k~W54)c۫T|x~mdEЕo UplX~PTxK {WX'{U;D`Yceov&zky%3dU]\*yme_n1i,˾hVߟ%aO) [nMQ-spCg*yt8.gU[Gڷj}7eE\k}a/&W;# v~!/ӷwx~,]+ ˇX`_F-7v+m庻j׋lMZfU^ U&lRڹY xTn5qL#Ұ|{ica_eGR"I;^96嵽]D%ȎR4q!ƽ_Ĥ7u4 gSRY=0@^Ͷw7]t_&L2*>꥖}vO1*Loa|W|_ȫpm^ M%NL;[+2螋0?|sr _tǝ쫝nRFNjmuKZ̳oH9t^$|R%AmIXؾ;잏җ/zArozoľ.Y`;3۾qW,Kr4Ԫ^u aYW%{&L)>Ӿ/J )uQoM̚0\Ƅd;iTӸ}'Mx5I7 ݥ(jBþ`.UĴ`~yWSX-I '-IJ< {}p02Sta_ }) ʮB%wnn[9^~ >0誏e?.2}ANk\Dvocy}dzfnUe}F(ݪF|#"Zj~\3\`w"ae-.yc&- n91}b\PpY9+/}} y ?DeUm6]>,yF0L>3kc*MWR=kG}ر_¾#UQ'haYTG&Čr1+ѼY̬nd ~}㏱lE%WƍOBfom_; yR}{1#u%Ry9fB5oߠ^ez%UcaՖ@;IRb%xJ;3aU;H?ꥷ>9+̾1&\w6*`Gb_ XvƄ$IhgM o-l1OMb9#pozY&ZFaYIfM'g)Z7 謗Va#pou᪃llc%.y]6THjt0}},_vŲjxxƼ۷˭oT/ͷo ̳P%#0WӋv,*y:փ2)>^a׿~ݪ}T'j'>}6k΋vwBZ2<<+A!o}QÑtrȁ}|wPp|KR7d5Vp.#[K[Ret;)'g`tZOȯpe^{ڹY5֌˚KMR3VH5Ra fh-Q.V9\Z+^mܕjvL^2-Az Ho޾Q1C;NLH=S,,Qeg, 85 {*Xnߴ_JVþtt̿woY=&@8$V̥̒"tzhlo=lvof@)գ /e?uu NO;bUN?cڹ&U(}j0rp5ٓb}#SUHLuwCRþY˥]Z%zMS yVa߉To3-۵oـ׵orh&;3+ .)tySżY1׾zNKwjSFNUW:Df[֜ynkXOeMR2)[c@YPo IU$:$^mS]tLfc9.-o-x}i79-7խt;g; }Q;2{6 þ\`d$;?2J׵>]OϏV-+0wy7tRaz`߹T&T3WӺNNJDWqW6WbXG2͈.tu%4t(}$`߹n=Un5:VM6/²aʼ7n VoH !aάoLA-d5 &.U4;Lb݊Ir4<ZVkt};7XjFkT8.QS 컈'ؗ=wRUv^[K fk(|z]a տ~U ƆӮ0 .e}߷xRUk#8 Ҙ}cLWÓJFȴ@e3Hg;ٖ5g[_FfTX3 ݴ+gž鏴dr:b%;1t;VyYW%#W7IUYAxl?{^t{}P79d [ þ;OLyqW@s林%M#CANKe_m /ۤYt_Rc%[u8Y a;  5HhU/oFվ.YuLZ` OQɌ*2˂pywʱ}*ea4?;|5R YtwfvE`_OygJ@|F'U1ֱ%^ nlo_yrt%m-a7IU!a]/H2nIaTTpԫkk^Kڋ ?2e9xټ)}V{kr$ȟ)ꥆ}xIpvYEj N}/r捻"k̻}zuz}2_)GFϳw1wg¾צk90U(/U;7E/ Gb`}CAu=*/kbjFt6"yCPUi$smKi@(c@dOgl;9 6`ˣu#>Ck+xa$J7IZgãO74 P=qT&*I5k_~>sپ^󢵑›,!i5|$t6a_` |ѴXCY5+\2bXyHU*b6N^DL[5 /6$AUxW>dܾq Ek# ZCMBcmʅyѰ/0oFdٺ;C5Tㅕ}yUBxXo9]3/ۦIwg`_9YԻk`b s]MJTj0&&>:;J2*^$aߝ}7d- .TMcvOTlf-Yj#cZ5e0Tr|K>oUH6oa_۵m:0r}c7l_jV5ռvn}9YFKf2WoB VZ^z_V\kpۋm/2"oveZgT TyM E+}[_<~KUIrCwg`_ E;'+к1Ζ,.a`_YjaҾ6$ߓn  ؗYė<ȫ`_ E>'+ v媺r]#I<5Zۅ%5CUO ep _طԃd}ɜ|4v+Mo#)#_#nj_v]?%.v TU`_@tBko *j221badwhs2W^)zRk_i7Fc9:V}. U\rTo}Qx/nw5Y8:2s\v}>[|~j`G3㛤E˨cp/K>G~j߸j^`ߴ8;zc!]s YcnvsoFDf-tjp\5'l>@+5ͼf߸^橤2,I-i%?m 6e}3=j- |z3m@_>ž1eoj$~:q߳r鵋}d_5ߤ9ƲlOϰo(T5З?ķyrf*Vrή}ej;a_5|hy]z}K̾Y0d_rϫ̼0w?"-z7)Kؤ򨕭2>^ry08^}\Uz2 F~>~#z[⤬d ?uƝ}1+wMڡU`{'9]dA3sXif6ҖY3;| ݮ.tN}V>En`?KgoNʙYHL͎5TNr06B>aƩ<`v<(}%;Uw<ݭĿ<2wEvm wZ`ߝ}Du6A?tlKvqD!=#JڭGXrHo%c CyO ʎoY>gks9(_y$WHjM־/ 􃄲]kV3Z`ߝ}M#ӺvK&3҅K͍$G΃7=Y=eY[C_M}w}|mfT~Vuˠ`¿<\N}wg`gz^brXu"SSپyG`m`sn3 ?<XH$_>{cl_CR$vnUYw}ɀ}wnTSpˢ *oFYTGp |h>k_Z.{W`/r/͙u N߻DW[#;*F`wg`_ÂvJyeMu.2?5z0_F<}/$gzl <Ökհh&5J6Ys/𡴬J@*g$\v|rjt(?*Y0Neg`V}e'`e`dNV$5Ĥp|7=&,! KFW څ0%*nꊭ{^'[Ga.*-/^-r_׾ ]2-O,)b^^*mMUU]|/U0'mSYUFְz;\k0- ƃdߑ)Fy%+P-;¼/dv3͸o\sj\/Cʵ*U )ߋ>W FgW7IrRfo%9T0QLqUS%H1W;Lв†}]{2Y*-/xՋM{^?YRIՔ+*!ѶjË-.Ksde ߂d-cVDAUUΞ,]aT)˼;iܷ}pI3.*/ "/+^|Olj7Y[I5R%Z%At |(^"^c$\W-3VIvþ(5WxTLɁ}К%uUZ(EGzMi6WV%yH>95ҒK^*aߝ}7oz>S+PQN9eU7[;z4ɾ4?ך&RxS+.ZZ1#cD}w>T{U~EyqVrb0; 1VV9%n`}h9wg`_tɼhmKڴgE$, $`ߝ}ؤ+΋vy^gƆ$qH2AP }eIr^˃@|n%#%f}gLeo0 }wנzi>k"ꑼYew}ɻֳ\Vp^W=|9>i 3?>ɒ}w`+,#1y#7(p.Ok=W*,xؗz$ S%<ܑh h 1LT]ݰ:/zj=.U~AeޘRu&Q\,w]aO`_h}],(쫵%/#f]Vm ą2N3Eߛ$UߑKCl;B$A`_p5w^4= KS̵;k?K*{M5G2RM s9L N ?WI!yCk׌\3tlL/7q./+ E@VήTե:>WjXMa_p֌oz^$d3T7* `\9 xMN (*Uat#W//,V8Ի`vhޥqVc"W /*.Л nwKoz+Lng#ay $U!mCkjw$L g0Zwg`_pZWgٕg$;fg[Od6`ߝ}X\ʆ_i g;(}d78\ݣ7RoQf?~Y?G`_#G>:qv2 ǚE1aNOdV*MAf\LpN3xM/=`/xםU4þ#+p/x;[q WϢd`er; ʼ'Jg\- l~jUNp;mmju]*; x}֬_mp(V޾GBw6M&-X2n ; (9.f*YNTmDՍ\w5w}[Z-h崫a1jǀ z/(uǀ3HqDLwMZn`6(#mU\- >y} M0^Em}N``K t0jXʷR`6/09_`"`"xP`";p0fec}x0/sQ-x/}/X V}j`_`5/X V}j`_`5/X V}j`_`5/X Voğ endstream endobj 78 0 obj <> endobj 83 0 obj <> endobj 82 0 obj <>/Length 33195>>stream x۵互`"KV#nby( tD0 03$cp`\t#~׿ ۂ`/* `/* `/* `/* `/* `/* +[qWӑ+ﹸ;;@ +jp.[ށ7c`AgնxfjY` lV7v-3٬=66 ok钽jwಱ|${v3s'*UXۦ(^-/,Rۆ/[+Ƙ˓ڽ2Vvl +mIF?B[m[ۻ`||V%'Cmmji0lVy9Qw@6 |em5Yе]ʷ[\|ji __٢qHq*-z(ߥ_ l[}V`_Ul[}V`_Ul[}V`_Ul[}V`_Ul[}V`_Ul[}V`_Ul[}V`_Ul[}V`_Ul[Cϙ{/[x55+믿wr!. `@b5[lx^UG!wZeqY[%ZiXg\rUfxx**̬V!,SV".V[pAY+ \`gUNت_i4eVDLVWP[l!q. [7RS6 [i< “dP>!VQ, O`AR`̉e=`p'n:tB lupYx* ; ['d(\ +iolrFo,,[ J:VBEQ%m+jWȃځ,8v۷M۸ cҝ][-9n|~rn;o e`l?ci:5+.{JDPv^q6Hj$Gȶ;Q~,4VU%[+V"%-q[L- p)=s|e^v_ElDNK[q5(m39S=77*uYp(->{;تG'Gmhn_keZȃ*cqY%jx-6?@nhUBnZ}pԒ@X\`*N9Cȶ9-ќZvC~v~"jIX\`UzVuZs/yj#۾o$pX\`j5l bۺ[=T.lj3 ڤ"$7 >7j@JNH2?yEvI cl6[}/UR`e^ms |af`aʣ4==[}I]j{V'.*lnmm1sV`]!wG{luBf`> &>{c<5j; >a[ >GZtg]حVs$pOwZDdhتCjUMLra;oD%O yp@"; 8mcc?]b̥ 辶ؿe#4^zoj#Pqb`|I;N1ϥn+VkcWB[m̫ʱhRȻIf`ZnS"%V 6Z2f%IlȾV7Uxت٪I-mOhvrOl"1lu~恆ٮ *l:9xwU2mMK!|5 U85V-%;nu8vm.[jYU['`x[̨myTL_b}ʱW$^eU5`ت1rDt'ϳvvI柎Q [[ՂzGml0Q࡯`o R[~(M c*{Va?瀭EITb8[c0jBs0VHb0瀭J᧒Ruv(Ou-WXC< [>l5*notVBʱ\Qƺ E[VÛmJNHn2?a9vI cWo热V`=>wS )MB2,^|a@m[}n*9!IQW:!vyxVa?pw["Rw~"7sQÃc;#l[}7ծ[Pv(KV==[U&*nw[Vö DʨWj׋R$|O;ǢlKr2 cl[};etg]xT޹Vk{rClOz[V|[7^.w\@ev[V1]h]ރ(SH])v}%2#VfV5=؂Uurm5om"-IbUKq7?jIƛ| -F0mFz 1jR{^QK7cM.*:e:Q|uSl!re}>$pXrloj~`#⸃QaVBn+l!Dk7K[VfY9ml懮jMgovvQ'Xol [}:VNU=yXH;JYu'2ZX7 [}تsŽaoMY>/VnXñU lQ`gHEՏVB&$+ĎZXC< [>GeHMwS )\;m=1Zjb05\;U VlUX7M%'V7 -ۛ6KRo热n`y*tSeR8u~[Q=B6OtF X,:!vm@m[}w՚%0rS i!'jص [>{٪nb|cF)[<|×x,dDcQ__bl[};۪Mⲱ%xϗx,dDQ@[V`b[mѶ0[tӮ·mh1 C6O4h&5V5=>UU@~k[.bZ^B6O4x5I5Ml ( _`¿4l^x1N *l :w/xöyʤkcl[qw)%]uӇ7ծ@?bȥlޛh8jI`.:%<<`%تEj\hbt?@VWaخZ|w}n7&jIV [m&D- T&=t!lՀ,aVꦛ)k]rU}U}n7&jIS˟+تsU-AώOvQ{jr馮:pԒIM~``*b}|,=Ձ)j~yHb74 G- !i/llu'jCNbl^!Ź? D``∭EO$bKvv!3xFmxVaKxƎaQB7դ[WirD+pǧ[HV*Jg쳷=zߐ3J4\Q Kl+n[VZN}C.jXlagxQګ􀄆b[ vk7d8QUhnxvrb i?<ⅶp U{Ώgcm;j1J7;6B*V_mn=GUɫvxGIjrvia*V_lM5Cj?_ g yˤbH?,dUT zNXlu lU "nm 7{[go2^fLG>VkOV]cVV`bLX)pcd[|B? o<:}8QKv>/U/j=:9jZp!Vt0[qϟJNzmaWsi1[m4Ncw~NZxYJ0vy8:̽lQImXz{njJÞ!sVBurԞ[[^*C$~މ՝S9/I;,k `%rӨ_Ǜڪ2uV2j"j -;Mw>XV/K~:QD+0cKkNMs6&;4?n'ت;Ų[}³ B;j2[5i6;4Q vYa^plu!$hrYBg$@ꀞj [Q@v,Ѫ{cwBU%ت#%㣱dgRck{_[=oc[U l57ͱviQ#jMqۏIi[85:bc`JwH[KVY,sV=j~zVZ*nU`I5'luBa?: [}FAnOVuɶZk'Mqj/ ;'[fV=V[s=VŽlXJ[?{dy{ <7>VkǍ热kW&{mu̫ Y4zbwf !w+,z@mUjҵV7l]lei)H[-67J|=)VU[F>l'XkRs_ 3ٟj16SȳNRXlUk1P9Vϼ~IUL[a C SO@f Eώ*_lufxVhl5VUjVF5g&zچ/[D~ogk8p愧nmGWgnQa]vb!EIcR=>8.ت1[ՀjUj񲫝mu ʶ}QO[Շ*K4X7::̀G% `(>ћX/[ƏVMO ֶZkoVV)j)%gw8QNЩ{X[5iU5mU] `bQ& 'JHzV[/تluVLjCUύA8 [-F~GlyĊMbM~ g/jV`cVܚpH VcU [ ]W'F`rmx|7R [[UjtjhB{GSjAB޿$ōBfF +[ ^[Ձ*V_msֶzW{vlf4ov#AfJX7<뭅'Jluԍ [Ր'kVU8V/lf,jf rٿ^UƵ\jq{l'`3>&vU%|>0zeϫ ͷPc%KlRO=۷v O=x[wٱ%Q+zG㼣P[ՠD9Iƭ*2V5Лkp[M\Zk lU )&!]/(yhk8p愧nUpVkz:(\ޣwaVCEXd[ .jn6uVu٪DV H>c^*zY7/QՀ*BYDmk|.4lUÀ~VwlՋ{+FmuM᮪z&Ifyn߆e?ÅتH]lV,B/xm'$ng|X>?\[ bŇ-n9Ns`񅸣qb mIovQvcy C3U5`C!2&j[ LLYتlU : m&!'pvjUXձ6aylkZՇlU[,/\۫9'jߏmծCDUϮVBj cm_ y^X}xVu`JUwxj//\OJ=-H|~κ[hr;d ]E9dGU/3YZܓb3lVThZ࣪VϨ|7\8`U|V^8VkɖްU%{}'i}VVT՚n *VV(zg\gx-49Cڞt/q&]*y {``kb9?!\kU22Py;Ǣh7*IZll9CU%[Ux#ndquvVɶltzOIz ogMbتa[I&E|Oe3üaCo62쭌=V`J7x[m%%'8_ֺIUXwռee*ch复G[{*V`o䩶z:UwٸVW<|ue / &I"aV(=M.el&٢ӕ dV Inqlo(}AHeXT8UMpᷰVɖF:[Uk&d_Җ,>:G6 P YB_&;Sr0wF.7bd :-vV#jOMjM!l&q#[ݷJsWbPUeHDI] ![ͣ-NU6ֵ}vj(H^#դlVT,vIdO[;_'ϸv_#vux [(iSYzplUllh|;eVwUuZ?˪9ϥ}JzRzG[-}{465t+Dc U-gNl`Ͻy{z TasǍQcdK; yW]z!ɖ ;ck]/dV۪Z٤zܕ# ^ծSm͟]͂P&j]{B::{rKX7ᨐ~JmyGkV͒-gdV/Uv׼Z\=&i-l!4[,>FfkN@'g~* ]Q tRrGkV3*U{6UleЬo?W[ sY~,W3}Uk{UB{r{ܐsR2o"{捓-37VM$~juUZ|4- c`J^myaij(qsyռH|2Dj=ji+8 {/;Z{Q|Vb5[czU%ՐIgL4mlloحgYVgO>{j:x c Z*ݿa.'U=;kKhFywUVgjU'![Ճ*yn :!**|@x#ddO$ 1!Iׯz0_2'(ߘsjV V`V'D!gA?g Kg[zG_ Հl5O|c~;**l4X<:H1*XIR>O/OЩ!/e`eplU[})3mu,p`?7|md򕤆KZVcU=7yXplUπNj]vl|8|7'jxͭ~:O>Z+**lU{Y|VNN1x9p=V_ʭm5f]q7Ij>=_4i]FVWj&*UR?wP PWlZ3b@aU?yձNyB?c_}Oj;9^溌J=ͨ汗ت1[ܜꥪ:z[}*m5+,Øj&kpeN4y۱_^XC^-8Z[-`zl5U*܈=luw|VU!γtc>ٍOJF vl#iֿla'[F &TNK]WlUO^fYCߦ_'3w|[}#N*ڕhiF|(=|~k> P>km5ol1 ss|U%mقK՗bh]PϱUcAA=5+\ne^Mr]Ӳ/5bf5U W«r녱kSj`JyH/V #D* fٶOW]:&=|nl|!^Km򃰳㻵j/تlU :#k#B&U2r\j_?VF?¤,!ߣWLCw9JVy{m-/O6uV-V`3(PVT!tmUu,xJOiKAo{Ny'*6=$5 CiŨ_&kSllU :rl3l[p{,[OnyE}ڪPZ\Ȓem`b0 [Ƕ5u춲1M{VV5&hX Qˑ55ļᷭ;_\?]?lIZb0 [G&jmuy:l? `8<~٪2\XO[K:UDĪoºt^S^X}xV-V`XkL.&PXjʖѽ۟ee޵f|liU5Tl򅶚w'j[Gm>VwS(yׂ[ ~U<򊭾lU :Vm Qv+~^9 `]!?Z~әjrՁVCKXo$(b/[UIWpa}V+ |Um djl;V3r@6U5aVSPô=V_ʆz|^j8pafa>ڎ=wVjV-Ǽ{V~z]!ge%)1au? uç'jp?cQ?/F IB[cWlWi;[-!*cS[  i{0M΋~? @X2O]n"U ژf4dI>{#$]تdǰ'ZZ<[D[hr[j0?I++IԞƣcت[ jV&\#h3q~F{hV5]yj#}b;xF{47{>ɥFˏ%xFm|[yh#?;e~@~!\c˹[9Lv~= | z2dն0n|X󥂅ڡa [ ͪagjZ!ت |# cψ_αTu]&j7V[{_ջjP|wBƵuq|yf߂И,siߦ_ s=VߋVkYTYVX-dܬ۪aٶeh‹ ) FO tY^{h %#e-]Ai΅K6bzڲ`Vkz5ZXN|[5LA5db-Vݎn-NoWҶ҄` llU :|#ЪU9eZդqXO`OT0 Աvaďf̿6m-QU$|>تlU :o\7ߥy[Y-YK~7UMZ`O Va]n݆]%+dO,DA5JtN*$sU vkLzfVxsĤ|pOjwg [}0^ 2'eWd%L d[2 U~9އ{rI돇-yjĽlOVa~zYU C[B_Y ®z;V%iiulx`P~ U=cn\(.z/[;Vf]׳lUlL/a@@ly}0M"ju lO[N^avc}Qɖ}VMhLQijg'Ll8jMUzjnA_avsd:>?V㟋eW# Kav6c7{ClDUV Yd-Gj[>PPqx~-R䵻/%%l®VLPTUXb/Il(V~|>llU :ou}GgN;h~v'Y:?5w#9ڎ\w.-m\V͂#Aាz@m lU :&Z w@1VÀV'dTpAUq/LLEmf]-qՀ[Z3ԤMqkm]cY=JۆHB~d1~Η klx]CnU5_1h5`VJ 5&Vi1)G3Z̞/ ņD*;+jVV`SY~)^~jrAsD5Z3\cAc_舓7/fj(kIznuK̇}lU5T_[UkrM2t{Iye.ȟoZX6Џy=URc>=s PⲿnM^uΤlU5TorHdc+ay6=V(Uo-|yPQؑQ:cV`JթEm5tL>a[&:qn[}T־1P7ت$KMX9\jRl-ɠUMlτUukdYšj҃ɺ=֥VaV}]}NW۹K4kbj+B'. ?Ey:aªWNC25y̨$ɞ9h؏Ǣs]]X]།Kçj޲iOWcbZT!wOOE;Hax/#[ulձTO,)kyVA^o?/0dn7m! ˘o %]egqDz 3e~smLVFvql밄bzV' jjXXm?4@opqaOw?X*cMXH䦇~k*cMռA|7jAV\RWjȆbHv̰a\7ژWaتتl`|ǭ=rVckD"2,>V+e%ekw̰aV⻵fتتlu1){TU$ѽlԈKբH2@3g F.8$ V/ojyZ*VW2 |on;8&Ebm<=&YYzzEko+mg4ڨD<~"YVX)V`&`JՕo8'ڪYڝt_^%êZ졖y+.9?Sö.[=m[[UdO[mרj6\Z?xL=2$Q^l/;M m_ SL*[pVcUتlu1%*+jb1GF.dOj aV{en3${R=[]I[Vݲ#t o迣2VǍiOm'aɤUlxɥ}Nƞ`0 jXo/V=Uhԙ:U Va׽2kj|wgPbicUpdHl6dUs[Ք%:bN*〼b[U vUDcn ߬:A?-48oаaV6 Gls[?!lb k f%VEz4>oglbIylja}Vaت~~}(ȗxV#-%\58לi¨2bVڪk߲YbcշZ[dbCXflnc{8lVwKS&‹cت)V*9V*8ҶU+U ت.Ib&|lm5ߞlVXdn [݄<_lmʪ'Vc{SVCEXmmuõk-oIluxm5oߍcЖ-[}; [5T0nm&*q~ተpDţ#bcӌנUelګaT&^Xl lU v]|=gXXsqaicwª><&ޮUCU%yN;\%5>?o__Fg}tSXl2j lukV=c`Jx I>V^sB՚J{eK6H2bQӸ4yEVr[Lj_?z.6V V`+qZWCx^UɶG4ThYmxZ}6Wհ&' _&]% [vuR+jV# [5[U>mR+m/>%{Q#޾7PjO@:AmM+%3jGFڞ?|6 i|>Fhتتlu%{j#i>=l[=5fr(lwa6fszXV켝&ah*[Unj [] W(&VZ٫jżp'3ml\SKkJvlV`+8gvԄ+v0@4w*рBYWW6clR )ScQB[->vUAplV`+yA.'L±,تGaxIRyƒ:sa.[nyaU #@[]-l52|*o#[UvUմ}lXI]n"& βq~.`&L^U [m =VWr []>ѣs OlvUtzHM+`A(*.jkUydiV'cZ.9 o4aVb|a۪|Ml5_'NIZ+ꁤ}UU!i;*[-l%9B<[V/45`H|XcM d4:ଓXIʮNgPpҹ)V;x>[LU"_l<:piMUsZkVī_ w {h-`8I3jlU(* ՠVlU[1[[ƁzUBrk PD/&zZۇU8wlu+r*6kj[9tiOշvbvL)Oc  { OIU6.\m)P+^v&W%ت5mقKշvVk '{7c.,'[W:F.\/Xت-تlupbj䛯 /TX2a")sꩼC!]7Ze)Zr 4pes8 ZἭ_H[(llU {j~a1[2Я¤ĖNƄ/OJηZeZV%&`U5J~=j[5[UnAbm|pz~E#IrTfJR?ºguVXX#/ WVڂ*V`[Pr~_oH2 jeY}m1_ [.bت!تlu=z_lu۶.Y6V%mC 5ėђqjz, $\/QZrQKت7yS/:ʐ֪w9yk[ {UjtVҸ;|ԙLzPs8xhOEU8U A<{4Qlu&l!Ńm7UyT,ޚ(wzX-&ቭ& U!y1oBJ8{lP&CVM6V/TW[꿅}܈H^n_0Wlr?˿F{l*:3˜O>s[=V V`e%CMsX%/ V*)00q+~ndy[eV| 0Ϧd#CTNQkyxz_4)60UllՁ[]X`pY Vb,uQV+75\JgV/\FK>!)t+ d+5V`Λ:SlUj~9GʤB_lyae.Uu`j#\$jWk`V'kϡ(m5dN۪y uZTKbj [j}9RVGf*VZ[ [ OQjp[6|/[ORBOmĞ:8e4Ov|}&uV9exrw[MZ ت$Ym7&9?l~`b!֭yR^F]6NT2|Iaxh'mV׈2wIW?mjxظ}l5[5g* : %dڟoM%Hq4xgj2wʤڠwn*V7@m ai[^[ lU ?Xn~UFP6&6:o_lP>=O(E1=_ܐQ珇5*Z%i`hN~N?OݫvW&[ힱV`ƱFtydXAP5lƊm v^?yc),q 4Vjh kcݨ9$UL睥фj"&fn`JUCڶ*/^ kYΔ^ђUaW@Dž{Sm4όb.[-SOr}t:U$BV^͒gl؁KVbssVw[U>Yx]z&wmUic*yiKq^b*As#WږМut db0ҒXha`Jgһ™Vk rK^va%MIIފ=;mIOaaǗuʛyຸ&0[L̸͖v+j[}&*aOjXIgJm獞m*iQBǢ&,eXwb>d܁߷s&[ےj [}&J[|KM>?1￘ȵsDnmz]Fm1?o%۱\O0ѥ̈́Pլ8vf `MX*ɱ*$Gj}``JgҶ5(Jz0lhIEsv?cLQX/'N:mLOj2f8i[ogZG[[U>Ś|Jdo'$nMb?$o cc[Jɜc/]c%Kni$vKfhjhl5-ܘ2k3y{X( P\{0<s=x7ګ^:Jgp0ׁCV>^.?GUmۯ!L;9L4F@*@Şr՞y%M%-?Q%+EIdNi_leoC#M>hc3UB[9 ^@渑{T5ēQo ͎5 jqAEG練+TV?*3@I _;E} VO Q$^mT؉Olnd T ?}%`:гm*!&'d#9qϽ^iJI&y,)!ퟎ~I2C+> j.l5|ŸU7wy=&MHI'ԚT%vj]G7zHxN~_3öWReOC9++X4̻mlu/lگԻ93^LaON?_wgms k4 ∭|\ڊڶZmLrT # ʄÉz{TeBQ~*a38WbNX*%a3w3SS3pMUD헥wW"m Ϥ$ITO%It5[PUޥC}gD=;}z تتl&Q{M8tz4y1Iw˅uQǍU )Ԥ.vijO¥x تتl&qY6+؛q4Uݏ2]Ar[Se8)~R'qx$r,W *VaϪZ1Nr x_IoJ1Tevlu7U%*\`'Y;mHVEWcsHg ԏֆ)jBTzW T!s$r8$;C+`>`JUCmMoYYap؛KsY;M:ftMq2Rn .7 nj>ᩚ׷>[4< [[U}LpXS 7fjNcSISdt<@/j%UIJmuԃhjت9~M5lUw+aتتl κ 3ri+67Ňqu⣼ |'c}HeNt=y:jݥ.,`gP"/&otV?4<[] ϿlX R&>]5'ǖ k`%kHdޤ'UJe:׏FHEkli-ZGe'j$PwY%XyUua" gIy@تlRspK9!ɐtL3VU|5uzsvSOt RJUsͻ2zw]GRT&*i2z*kzs^Q5d/Ĝ_>s$)ӡO{)jeOl.'fkIcdoupsxgsUΩtS>u>'Kw̿yߥ8u U%*~n 隮t~X>Y1yJUx 8_a]9t@* ihB we◢ֹl %]iS&M|_3y=!nqUx޷baxנ8wZe?~ٸ, !J+l@7H?磍Mz>EF>x̗A|v6)W4sMQ'ݥƽinۗ.ՇQ[0aVwQ!m: mwͳaF3|ؙ5D3UlyW.; yXoҠwŴdoi㡽NO~ޡ [[ry*p'~ 4N5 0^M+Y.[>iDx͋ 궿U(0gl/¯z(]5HI`oɑf}X.?qɟbZ鲤M1JqU{1zI 1HaWF Ů 漙g%=`sT |7ana(@ZbQ鬥sMt9Ɵ`“[a5|+]2,OzϩN3Ht~IӘSI >\9ҵ_ۂQVǢkz0^QFչv_b;sǃV`$NU1X$wrB~ 扒&t˟p̲  [PE<Ago^vkWn&?$Ei+R qÌ("*\ _UW4y)(xKO=V>뙼-P[PTUl?n~@[ 4h0x O82ܝ)Ό~sȄ ]c(j|ƀWW$`A2-i5N~y(j6i'u$K3&]Dk>< 4l5&Xv(*z2$KJtÓ@` b׆~ښNAUh̠=Y/rKǍammɿWLw䕳h?z9Q:,%VT> |O$RH[MB*iϦxU'ele d5U ~Wy`1KJHfY͚y,kM{&VԒ(d `8;3< ɼj+?VX_@d^#{kL[ Of[=7['{ ^Vz,.x-7> endobj 90 0 obj <> endobj 89 0 obj <>/Length 11586>>stream xmr"ɲ-PaMΦfOv|$khS!$ XkeYZ`]*VX Ue.kuYZ`]*VX Ue.kuYZ`]*VX Ue.kϟ?v^o-@re>|>k쑵z<,gk=w]+nWMtßxݧ#=垻{ʗp$ɯ3+ Gh,G=OynSIHǫexHڵ _(oYsZ#V/3ĽwV>Ew'WyunxddpZ-N2~e~ѕV0U8Һ?I"yZ}L 㐜Q=axWZðVFvj+Չi2k|ݒq,|lyNwm+f xrHw2WQy~N'閵zXiz+\[d7e}Zzcka.[ ju';K|(\~q0 -ffq0 -ffq0 -ffq0 -ffq0 -ffq0 -ffVOQsӎ= -ffV^gjZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jZmbʹVbfVZ(L k*jfZ=7&Fά̬Q쉨5Yk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5Z<|7~blbʹVkwP^V:q2ZO Śia@Z-­P*T"ZO Śia@j{5:X7jbp`V?z}g9M)ֵl18k5 xZ(L ϭ@sE:5ZZ[iX3-U|Z w Qu,vk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-UXk5ZV[iX3-U|ZW^~|veBfZXPyZOQMak5ZV[iX3-UuT k5Zo59VZ(L k*Kՙ:G^gզjXʹP*TUZmbʹVbfVZ(L k*  {1J Śia@oYeVZ(L k* ՂVZ(L k*o~%ZmbʹVk5ZV[iX3-UxJ Śia@ZXP*TzwJ Śia@V3j+-k ou7V[iX3-UXk5ZWdVZ(L k*~*cBfZXPVk5Zʛ[=-հViX3-Uuk5{1J Śia@{dVZ(L k*jZmbʹV2j+-k `V[iX3-UxJ Śia@ZXP*Tx%o_'~;(źQk;ZݏJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TV7sdku<-k _'xZ(L k*VX(źQkV4ku<-k kHVBfZXP9Z=-k7f9M)ֵl18(źQk;sVE)֍ZVFY L/]:щy:5Zǯ]YP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TՌJ Śia@ZXP*TVe??>~VGBfZ;Ѭ":5€%ـv̵ՑP/|=XP/|4k5cmomGl{ـffVZ|Zr5g;ѬՌJbˮU[1eVܯV[i(\{\߲?_]s-;q>ا>!ZMn/6xľa?{-\ܻأX?]lٛrٵ5[e>VoϿl{Ź?%? F.?/M5H(|;}cԚkoܚyZBVu#v`ݍ{<}~?w ^pן?N)9{νz_V?~'inm)QH?~^?G ~W~]uʬ3~ >}Fr_>6ح.>bOэߧwOr_k5h̵:X4?bnlhޔ[}Џ#vbϝg>Hح.䦜h͇jbZ=k2ꃫ%خkuN,v7 V)X쮧+G}I[𦼵HحE}M9Rcؑx{_k5qkŒ;KtG,o;.bOWKH{wW=񯵚V/+|Xvb;]P1Ş9ۗ-vkb{)GpZ kub)#TL+G%GkZزGlby:񯵚V,vkbou~>;P1SL1/hf޾V?b)b)fb)b)fy}"֪b)b)"]j7۲'SL1SL1kI֪b)b)V>Xf[b)b)f>ZUL1SL1bꝳku"~}![)jWLE {)WWu䚯)b)b_ {)WWu䚯)b)b_ {5wo6SL1Sl+SAs+YZ`]*VX by?_}yYbH˹zO/1mww^֝9i+ Gk~&v_>k%}XRi~^bg9bsoOߝ54wVFߊ`;+mS#xZx>幛/+ێ_O󏧍jQOsO7fn|Gl՜xom|"rv^)1f_]{\Qg}E.4IbIˮYZK=zk_d+Ŷ?7I߉is{s{r&F6)5iV{Xإз=mnY|OybI򋣦K>;+OM/ 7;}ĨisS]l v!?g~OپVW쨏۟677{tMکX|M9XⴹŶVcpzVݜӉSi;c~6%n/,ۦĨ}MiZcG!=@OL{MS{GMOY1Ͽ_⬨ž>'+(\X4k,مO|SLL{AGMO)gzڬ'}cfyj{ܨuN>g_fZŷ>/Length 8514>>stream xavڱQ<&Èdf9O7Z@CQKR ,_ PҏZ, @]j*uURԥVKPZ. @]j*uURԥVKPZ. @]j*uURԥVKPZw>^<5u.vv5^7.}^zѧkyn]ޘ^ӴM?<.32p(:{{ju[UZH!^l[J}:>~ë+t *AwZJQ7Y[._t>EbsBgWi2g~ڴgk,|b5N\Z-C.LxZxz :\k~ gPV'잯]d9{\^AmU/ϩ6gzts۴5A 뇯YٱV\^<э=toŨU&:pa.8fWfeΆƕ+&+ku1~( 7V_ P'XΧ:VWg.oZPpqkW~}kN>˞ZlѕtPNM7g1Z@X[?{\%U`+XU/_MX^?;qo?u^Yy÷V6h\_sw âWrz/YXف ۲M g,[QԥVKPZ. @]j*uURԥVKPZ. @]j*uURԥVKPZ. @]j*uURԥVKPZ. @]j*uURԥVKPɵZ#У3k7+oG)sj7bNP̩UTWVXGM`ɿW.Q?{?M6eY.ZjuZjzշG_Piz"*@VҨ0 FU4j5LQaj Z SijZHV*@VҨ0 FU4j5LQaj Z SijZHV*@VҨ0 FU4j5LQaj Z SijZHV*@VҨ0 FU4j5LQaj Z SijZHV*@VҨ0 FU4]o/W ]Vq9nͷrp¯+VrtVTYjaS p jαqxUV?1N^V*ajҨUJZ4N@.k\j ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj i^˯;.߻L9 ig\[\?ܹ ȔSZ&l_UV MgJUNV EjusZPj\VikuJ,<kիH*±UJ2 iԪZ%L@kuHV Mz.Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jtY8志_7,\wrsjWϸx[>?\ ȔSZMקJ i:տWbҔoV9Z4jUV jukuJ,<*1@NzTZ4rʡ*f:GRZ=ZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj i^˯;.߻L9 ig\[\?ܹ ȔSZM̯WPV MgJUNV ZUUHsZ}-o^Wbx\V [P@[]NJ[jҜY_톳~Z iNWFߜ~ЄZ4gہ55+PUHsrPB@xz*jҜ*ZE@.\j ikuBuj ijZE@`p*]Q[]XRZE@`VZ4翃K:U*$Vaj ijZE@Bg VQƫ*jz^U*:VQƙaj ijZE@`VQFU*)~tZE@筆U*)~ZE@VQƙaj i*LV w SUHs״^NZ*j|VNNPUH=*jҨ0Z4*LV w SUH*jҨ0Z4%zەg%.SnN@z:?[\]udͩUHs;XM/|R$PZ}VjjҔ8E iJi۫rju8[\@Xj[}wrsjҜ|뽫J*)CK@ku|@YHV Mw -өU*9::U*$:V;VQc/tZE@签tj i%5U*Qaj i VQƫ*jx0Z4[ZE@VQƫ*jҨ0Z4^eVQwzM4VZ4' 0tB@B UZ4j5LV SUHsvZE@"`VQFU*ɮ;U9o~UHV*j8 LV Z SUHsΙtj ijZE@3k6RUHsy!VQī^EU*ql5LV V*jxO0Z4j5LV MWY4{v΅w'SnN@kǫp¯(SnN@V SFU*VO*RZ9VxUVql8V SFU*Vtj\VU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQFU*Qaj ijZE@VQ ˯۹pdͩUH}x\eͩUHsZ]ViK@V S":zjCUHsZ|筎_@}z[4W8VIV ZUUH}:*B&SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV ͥj#_{|{)7V ujg ޑL9 iԪZ%L@[zUV ZUUHsZFjZ 4C:Jccӣ0UlV M:*9*f:GRRCV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV j7__sɔSZm*=?ܹ=ʔSZ}VIV ZUUHV*aj\V_ټVǯ HCӱU*ȱTV jujCUH}N(}$peͩUH}SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV Z SUHV*jҨ0Z4j5LV|ARaj*B~w׿?(VVI*ֳSakdjJ.jZ]xQ|>$jSaMjaYv j_!ewWV0&ꕔ]e%0&|EG]!\Z S]j25f!M|EG]!\Z S]j2Z-hLծG5vZ- GawU_j5Lv=4zQw]jZ S]j2M^lvZVjףLSuݥV~0&FawU_j5Lv=4zQw]jZ S]j2M^lvZVjףLSuݥV~0&FawU_j5Lv=4zQw]jZ S]j2M^lvZVjףLSG=?n6R@jZzTij:|wmV~0&jQjQjZ S]j2M6VV~S]j2M6VV~ݽVsEo~ZwTij(z( Kn&yx~ֶdڴVVǯ Zrly + {\gl6]X+Ů]Zn:wmckްum7\)v޶ժpk[=-~6nJkw'NjUalcߵykkcpص Z. @]j*uUo|vχ̊AçۆnsZ/{~Ϝ;<췎zSagp6O{SmW]kW㞵giln^5̟VsUw~=2ˣj5gZs"{O8jp}-K6? }{~(kٛxدS+_a7x{©SC'zC{}/. ڹb;t5jO pJPa G0),n~Ş{~&kVlB?wOWz{O8ju8a GfpM*vq{~Ϝm=?x؟b5p'sWNtfUS w;GM69jC/qAn;:x`o l-mYM7<´g5f,y64^krШ&OE΋6<9O?h. 7p<_nxt-|vۨȳ?^'o6^bG}H ;6?j᳛*˲j?NdvTS ӆ_E%jh ӆ?r=^.z-ˣ>$ /SnfPnؿI:]_a.Cg /^ouB6Zݳ> wyq?8:Iu5u՟A5q6]s7ysm|[Gt^Cf74hM ՘].3aAmƲ?nfj*-8ὶ}txc~59·gw5uˏکR5G >.9j UDF-͟vg[*mô +Vs09f;樅iZ廲?[^Kv&fQWMCjT=_pjd9jkZP0Q;UVihsĬ6i2-T=_sj04z7"; juPQe6Q˟JvnjڞQ?'gmQWڶ??Gyi5,k$ZUp4lsG9~jZ;hNim[|ϴZMpϕFy 45yJg9j3 kCPZ. @]j*uURԥVKPZ. @]j*uURԥVZy]~{}}wr{ $P͌->?Utڧ5Q@MjiV5iZjRm,o_>v v oop0x2U66[]pv{Y*@k5zmu} ԡVv/3ku*@{^e G[8Zh&VLJ*@K^JLCVN\(BPZ. @]j*uURԥVKPZ. @]j*uURԥVKPZ. @]j*uURԥVA endstream endobj 91 0 obj <> endobj 97 0 obj <> endobj 96 0 obj <>/Length 15543>>stream xkzJzl3l< 4<ͬOeм@5~ Q,?׿?*bV \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV \U䢭 mhE[@.*P?ǿnЙ?ȒBΓzv}r@>A7\۸{Caw,?ζՄfXV?ԖAh!`*PϳuwgehV{5/:h6؃ :#k|^uy 3na· >;T7O3aS{ysamg-oXgUxmfw#S  #Ogɾby mYYҽny{g>d՛|7-qS p#_c&V \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV \UV'xm~'.!}JU\|Vw^KAp\nm7|}}2&omi7V*ijxo7PV: Bk[݃ Ђ \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV \Ui_ VzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzU)kKY:΄ 81Mmo˼>KY:΄ 81Mmu,WVhSVA[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'F[V'-/I>8u mpbߖy}3NLS[A[V'F[V'^>D[UkVz/Ÿ?~E[ABLxopb~{7?ugB[7XV'u*ĔCVq2UVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzUVzU)kKY:΄ 81Mmo˼>ZoJ-*O_[% *NV'>NLY[/ ? p#^q&Uij=|t3NLS[= m'C[mG[mG[mG[mG[mG[m|g>Q$V?߻׿?Rmx$NU`!'V-^~21ImX'忒z[Vqdbx'*KC]M=!kIhB>VoXLLD[e5VLLD[7X}m';V^/O&&w V?kIhB>j[|+~ǟMn fZ{g{^^}ЏL`n7|:Cb@^k47XiKjhx[ݜM[VB^ݐ\CC6+$mAm5mmh՘ 54dBb@V]a='Umu𠛵hg`2vCr ٬8ӶO.A[A[})j5vCr ٬8m`%h7h/E[nH!rڶzU[A[A[})j5vCr ٬8sUj՗Vcn7$А 9m[ԇ %h7h/E[nH!rζ:>WX%h7h/E[nH!rζ˵ޠms!lVH z0ǾJqť,Vמrwoy ?jϞZmۓ? S^dn[!dپWdk;WCb0yVzvΞV sfXsI>VoV$$A[C[]z ꏄ=hۉ/j7h7h*ޠHH߃ϭjh7h*ޠHH߃___h.A[A[V mmGBbՍhz ꏄ=hIg A[A[V mmGBbWVɯ ڪgh7h?.A[A[V mmGBb\PmZ2UmVoV$$A[$UmVoV$$A[HX-.xH[}=oUյv;6i|ί!Rk\fsGɯ="VC:'~E[}[~b^8USkoyZ{u|6۞~%Xnn/ӯ_v n~}=ex!n%ͱLsȫګ#=櫵/G*ps{~`[<\p!/ p+Voug:UmC^^!6_Ͷɯ="VKႛ__y^Ȇ[zsl<ӡj*aϵjmm=K~7^_VͱLsȫګ#=櫵/G*ps{~%|}k72 mXyC[V9Ujžkl{N#botOw[ >zS3/.՛cg;mU[-WWG{Wkk9_kU=o__[9}CVryZ{u|6۞~%Xnn/ӯpmu!n%ͱLsȫګ#=櫵/G*ps{~%|+víD[9}CVryZ{u|6۞~%Xnn/ӯeڕUlh7Ǻv3ڪZ!Rk\fsx{U}~Y[}V wT…{cyQc'&g[Kv6 4?>q5^WҢV7᝭lِ[k'\m!ǻ)k3!=َW ~p|ۼ,ܾuڽ0lk7;wmvlpچKx&g[{CѾ>fڪ:m!3熧0̈́<:d;^}>/<>'oi3\/>;!ۋf 0muVMR[}?pnVxpl/g[{CѾ>V?ᷴVQ[ݐEwlko3WoڃN}m͞0̈́<:d;^}>/<>'oi3\/>;!ۋfz{1/6Ij;ᷴVQ[ݐEwlko3WV/K}VMR[}?pnVxpl/g[{CѾ>fyg;co4{¼6Sx?pnVxpl/g[{CѾ~g[bnd|)m-\vÜ\N{Yx=mv=ɵYx2l]W׮¸c~WgLʁ{mvlӣ8ƒ<ֆ~<߾ڞmux]bk?V}l_N{c百mծ'SkI_Eͯu9 jmeڞlZcOWgsj}/;;GyYp)*r?C͗Ӟ؃yogIj?fw̯6~}3p~D;۳˛=<jǞ ζ^w/vSU~/=WݱL6jדV6_m~!gwfߗ۷g7k{xj=Ԏ=^mϩWV߆~=mv=ImlrΏH[}g}Y}{vy'ہCؓZߋic(/ 9e^Eyȹrs{=mv=ImlrΏH[}g}Y}{vy'ہCؓZߋWVc(/ 9e^Eyȹrs{=mv=ImlrΏH[}g}Y}{vy'ہCؓZߋic(/ 9e^Eyȹrs{=mv=ImlrΏH[}g}Y}{vy'ہCؓZߋWVc(/ 9e^Eyȹrs{=mv=ImlrΏH[}g}Y}{vy'ہCؓZߋ}7X]V{XUmyogIj?fw̯6~}3p~D;۳˛=<jǞ ζ^볟n'_Eyȹrs{=mv=ImlrΏH[}g}Y}{vy'ہCؓZߋNz!iUwA<ӷ $;W_>s8?"meڞlZcOWgsj}/ݣe!ogdvZǞ?dEF[}j7gڟ?N3;M 39dVdZEd"Thk㮰+߬]Ei2ZEd"dVd*OOjQZEHi*B&k!&Siӈܘp2-ZEHi*B&k!&S^~SϭVka&l*BLV2YU4 M[FƄka&l*BLV2YU4 '1e![&ӨUL*B&k!MBV1e![&ӨUL*B&k!MB'-e![&ӨUL*B&k!MBV1e![&ӨUL*B&k!MBd[ԇ UW]VdZEd"Th!V]uaZEHi*B&k!&SE+K}IF"dVdZEd"Th[Fi!&ӨUL*B&k!MBiDnLV2Yi2ZEd"dVd*4`SUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBWVoF[uEi!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"ThmoݼqiP[uEi!MQUL*BLVM[]J[uEi!MQUL*BLVV{ڪWi2ZEd"dVd*?!ڪ:UW]VdZEd"ThghZO[uEi!MQUL*BLvS7!3>{h=z٣@O}'>{dGoo];_$1HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLVV7~mUU4F"dV2Yi2Z}[3Ni2ZEd"dVd*ʶmUU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"ThmoݼqiYO[uEi!MQUL*BLV%}s1ꪋ*BLV2YU4 ~J~\U4F"dV2Yi2ZY[jV2Yi2ZEd"dVd*4muSUL*BLV2YU4 j= =YO}'>{h=z٣7j(*B&k!MQUL*BLN#rcZEHi*B&k!&Siӈܘ""dVdZEd"Thmu|ZU4F"dV2Yi2Ze[݉ꪋ*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*3KDŽڪ.Ji2ZEd"dVd*UUW]VdZEd"Th4"7HU4F"dV2Yi2Z}[][U *BLV2YU4 m.ꢴ&ӨUL*B&k!MB;C[֛Rj= =YO}'>{h=z٣7jm% ު?#Fi!MQUL*BLN#rcZEHi*B&k!&SշՅ/7HU4F"dV2Yi2Z}[3Ni2ZEd"dVd*3յh("4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MBV1EZEd"4j!ZEHдiDnLV2Yi2ZEd"dVd*4muSUL*BLV2YU4 M[Fi!&ӨUL*B&k!MB;C[Ͽ,ꢴ&ӨUL*B&k!MBouGHޘ""dVdZEd"Th4"7HU4F"dV2Yi2:ȍ)*B&k!MQUL*BLN#rcZEHi*B&k!&Sz/oi2~"4j!ZEH)~7O` ZEHi*B&k!&S-dn23i!&ӨUL*B&k!MH[:=03i!&ӨUL*B&k!MH[:x'*rV \U䢭 ϓgϓ_,<[|"7Χ\-ع] Wd` >.؅ūݐ Kcՙ1m͏<%a˗`3!?o-\m pjvaj˿p]Wn¶lv=h?Kbۂa‡V[嫅-ضp!؅[W۹ V{Kbj;`Ֆkj ` >.؅5-֪չZ0ʶvKb.^.ʶ[kW.؂o}6 sCva]Ҷ:ζ9~|7?ˏ_sn vc›e- `ޞ4Fo[VdsƓ?$0~3^s?Ws-'~r;@?ͤ=I>pY6g5fsF^QL6g_X~/꿄v|wj4"w`Φ:ծ$߰H}xy83Wq3?.EH[?.Qz/j;Sy/]E7L3ٰ77W8%3]p;7u>뵫gjY/N@GoGZWY♦`%?hE[9y?Ʈv;=\;Xjvz{V;6͂'^-zj#R5'ph8!yj3+cl] چ uNj{VǮv#GZnV{_'|] ֲIF.6xj{VǞ^=\CejɷCgZ.+Zm-%Bj󋷯m[1\:ōq8Yy/GvxԗvyW_}=h8'3p9_!o쥭pӬvSv.xjG-ϓlu?\?OnaVی \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV`[[#Z:g7G[\7U՞%V4Rޱ6lm@#*,eoݼ{03o?<"䠭R6?;: mkZV`)>:g4UXʞeo=V mV7Xs> :SX•7[@*rV \U䢭 mhE[@.*rV \U䢭 mhE[@.*rV \U䢭 mhE[@.>v endstream endobj 95 0 obj <>/Length 14444>>stream x[vɖ$Pj654j6wf\|8aG!|\L>ǃ!#I@UjiV襭K[ @/m^*UziV襭K[ @/m^*UziV襭K[ @/m^*U~|_}Oi߾tg}`f}O+d|j)/. L ;֯IyMoUMhPUoy[]%L5m׷~,F?ΦS~ӻ9ٞUL5=?$m62x؃qhɃ}7._?O;܀+Vᚾv;{-~5|\G^G:xOg>c<7.M[kOnOY~mok;|磏| OohpMSQw}-~o-}~pxw>į?n) ky|?}R*\ t_t0ן݆۷Now>3| Ssipa*\=?~+i&6omt?vW5j/ݾkH&c} 0㟭n72YOv{ehpM=FIn ~>wO3<ĝ9~m GvK[ @/m^*UziV襭K[ @/m^*UziV襭K[ @/m^*UziV襭K[ @/m^*UziV襭K[ @my=Ƀ2Vտ]㣿<'9V襭Ы=U[ࣖ?e>Տ?\ }1mu*BV?=oem^y__yhkX[= :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ :hki#*Zꈶ @_sX[[_~O+@ m=R[?>>_M*{VyD7JhI[(Wjx m2e9?[XXϟ?}@ ? G_ѕ@ 2eD[]IPq.QF^lLŹ Gyz2m*e8ʈ:CŹ GVGUz8(#ꈶ @2eD[V\h#*=TpmuD[s2hPq.QFm*e8ʈ:CŹ GVGUz8(#ꈶ @2eD[V\h#*=TpmuD[s2hPq.QFm*e8ʈ:УecmuD[Gmũ V"ꈶ @ڊSEm6X-h#*rg[mZ6VGU(.϶j/`l,hP]m^jXD[V<۪kղ:rڋ6X-h#*'pJ۪kղ:rڋ6X-h#*'pJ۪kղ:rڋ6X-h#*'pJ۪kղ:rڋ6X-h#*'pJ۪kղ:rڋ6X-h#*'pJ۪kղ:rڋ6X-h#*'pJ۪kղ:rڋ6X-h#*'pJ۪kղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjX5oa>=?+gsJn6Q{ecWjUc>+gsJn6Q{ecmGq%lYڍ2j`l,mcVyuYڍ2j`l,@$=+U`\F5VE^Km`?h};TjqXmZ6y~*=+U`\F5VE_Εijgj7V˨jղ˷՛瞕Xm0. V"/VOrTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6y>WΕijgj7V˨jղ+տ㣿]I<{Vvck6X-p[*/=+U`\F5VE_ѕijgj7V˨jղ瞾%VyuYڍ2j`l,bmd['Xϟ?V)+wةڍ2j`l,b?[VTjqXmZ6VyDW枕Xm0. V"Vou=+U`\F5VE^L[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"ꈶ ܳR e^cjXD[V9{Vvck6X-h#*'pJn6Q{ecmuD[Yڍ2j`l,h=+U`\F5VEmgj7V˨jղ:rTjqXmZ6VGUNXm0. V"+.6 [؃UNXm0. V"{C}{M[aV9{Vvck6X-l~*'pJn6Q{ecmsU䞕Xm0. V" SmrTjqXmZ6Yn?Xi=+U`\F5VE V#*'pJn6Q{ec'|VUNXm0. V"ꈶ ܳR e^cjXdVߧy*rJnL0(kղouUNݘ`<[QecꝶʆܳRg=`l,ozVUo*pJnL0(kղȋ VOrp$=+U1xڣ V"Vv}]|JܳRg=`l,RL?VTj6X-ҟ_j:Tj6X- V|}ҪKsJnL0(kղgD,w2:mC'Ŕj7&V{jX䕞uZW`Rg=`l,J9􈮤j7&V{jXp_)KnL0(kղH߷_^_)KnL0(kղ ?oS6ݘ`<[QecmuR5VTڍ v6VG|l,U1.vc]E<`D[=W`R2j7&eXğVTڍ v6YVi LXvc]F ,ǿ k LXvc]F ,~꧿j LXvc]F ;F|l,U1.vc]Em_)KnL˨ݘ`acD[_)KnL˨ݘ`acU՛zj7&enL˰ʶO[=W`vcڍ v6VG|j7&XJ˨ݘ`acgYGn!S,%enL˰Hşzkj LnL`Q1."+ۨ/Vݘ`).vc]Em_ڍ 2j7&eX ݘ`).vc]E*՛zVݘ`).vc]EV~S,%enL˰⟭?cgW+0U1R]F ,~]j LnL`Q1."+;W`vcڍ v6YV?>@[_ڍ 2j7&XJkXL7-+ݘ`).vcKu[n?Xit^j7&XJ˨ݘ`)RV~zڍ 2j7&XJTg?[}W؃:/f,%enL``[}VX:/f,%enL``+QO]VЛnL`Q1R:i#zڍ 2j7&XJTg0inӭ8Xڍ 2j7&XJTgemOY=zU1R]FK V Vvcڍ ,yjժݘ`).vcKuVGjժݘ`).vcKu[VjU1R]FK hU1R]FK m`j7&XJ˨ݘ`)RVՏO]Mc_Gi;wӭ8Xڍ 2j7&XJTg#?ܷ>Pہ뼞njnL`Q1R:lUmz=݊ժݘ`).vcKu{zjs|QVK v,%X3g|ޯzU1R]FK ޾/||G5%J mõ}{[qZ,%enL``+SϨj Vvcڍ ,lzU1R]FK m?s,WVK v,%X3+=|jnL`Q1R:i#jnL`Q1R:y&Oڪz@mZ,%enL``ꈶz@mZ,%enL``+j[7J[=6Xڍ 2j7&XJTg5[}/8z`)Rjժݘ`)RִCym+K VvcKumRKU1R:yꈶz`)RK ,%Xde[j,%XJ`)REmRK ,%XJmh,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`kI|]t,'XJ`)RR[?>>_u^O7rK ,%XJ+O[t,'XJ`)Rh꼞nK ,%XJ`Wj7:M`)RK ,bmdK ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#K ,%XJ`muD[=@`)RK ,h,%XJ`)REmRK ,%XJ: XJ`)RK VGK ,%XJ`)"ꈶz`)RK ,%XD[V,%XJ`)Rh#Չ:/`9RK ,{_9~{K ,%XJ``VvǏGl;wjJ`)RK Jmm&l,%XJ`)R:imul,%XJ&_&$\E[V׎;m` ,Wem6 (WVGյN$DKmUYlM9UӴmu6 6`M^-I0Gj:5w&&,Iڋ_6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQmo_9~+M4wiR=J$\5[X@?5׿{+}+M4wiR=J$\5ީMlᨹl,IڣlM9U^j4wiR=J$\5M[ 7Qsml"Km([h`r4mO @ϟ? yQsml"Km([h`r4?[ 7Qsml"Km([h`r4m*t^OsG͝Il,IڣlM9U^e[8j.Km([h`rմlV׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM9UӴmu6 66 V{-I0Gj:5w&&&jR6 (WMVGյN$D6$XQ &iꈶviR=J$\5M[V׎;m`Xj`G)Bsi#Qsml"Km([h`r4muD[];jMMdcM` mQhkG͝Il,IڣlM6Vl΍i#j.i-5w` G͝&Qs piꈶvi-5w` G͝&Qs pimu[8j4;MNlᨹ:i#Qs pi-5w` G͝&Qs}c3V[z6~z7zJPڋ6؝ViQF}۫m/\[]~= 6%Xɴ;?Xɴ V{J?Ճ9ʍ1C\įGFM^(؝J6v~_?^co/L, >{.|(Ki9v=}|ap=}}>lps_~w 6?U/mu!_W>z³}|MW`m÷oN2lJ']*I3طK{W忴񇼽ӱ}{߾p= &`;l1{v_V?ۉV/@ &X &XI;e]ӧzgl &` &X `w޻ʧOϼL0LIwL0LI7I[ @/m^*UzmV_=ߙ] |"_x?8moO#C&o.C?ş~\ѴO /{c\u_]bѴ[<6xko]Ѩt447.hos?vy/Gh}ر}<ʞcۖ?uo]MOs?7^i~c㞕N{p/={ovS4t?~N |xʁ=6c,kGZ`w)3؝og;ߔNs7E?\>\<~w߾i{Izdc/z0`.\k{o*/J[L7RS_[O~QseQN{oM 6|uq3rΟGb|SIz$?$ݞĴY2IB>ui85wړ` =>m~}pcM?N{ooMG 4k*e v_οiW5[xx:8NR[Q>[ a6ǦM)Ii<6(U[[OG+xiW5Loﯼvs'W{ҧԿG{q2_%IO~6m5 mv`o ϩ~ {{6o/Ltl#~xꃣ~3nS=2m_:#cӾ}Ɐo_4'~_=!~鴹6|*3>i߾~C|/4K҃nS?M~ImiVO?zNu|dcG=uX p93텶Eǧ vʎ^K &;O*x/" zͿ`Ϛ+5G=/UaY̚q8k`;wo/L-ƓOb^xb-5}ړL6뇾?8jִ~xσisG\NO¿[0Sm vִV襭K[ @/m^*UziV襭K[ @/m^*Uzi_t||y#}LGh#ڧ6xS4G>gVӝ +}9<`=̥Vzs? $*{fVB*=ou__f[s&V~ȟJ?g|~ VFҿI[L`[*/~#?!wNk3dH I[ @/m^*UziV襭K[ @/m^*UziV襭K[ @/m^*UziV襭 ` endstream endobj 98 0 obj <> endobj 102 0 obj <> endobj 9 0 obj <> endobj 11 0 obj <> endobj 75 0 obj <> endobj 13 0 obj <> endobj 14 0 obj <> endobj 7 0 obj <> endobj 10 0 obj <> endobj 103 0 obj <>stream @@ &)̜e; SNaM*AwlN1J:&'A p =A)88ܰjJEqHV,!h:# yTjuQX kqe6V:b:(Ȝo 3)l0zm`QLhBt;&#f)MfZ_I)$%P\X0EpJ `4% TNd ) )  D J#3$xR%gp|t2 _(%E&X7 >`Ad$EdɆeA P 2 H2 b`} fEA(3 (0PWFPq>YeR[P9O><{'r|DGiF"RXEC9 08XB ?x!4(P$OH?9EC1"t" B PwĤxEQ $d\k`I"$-`"pD 678; p(bE`+T`z%@`pOp>CaAth!XH'$Ð| @kZUhaT uL=P} 4/@ q#dI!(B BhY b91DB-!$A@Ȃ -0E{V q2~Ah&lDb\F11# €yC̏/TK'XbT= ^%B0`#D zpD<@f`Xq:ؑv3 $Aat$l ``BpB!E~x XbA! ɏ_26_|vaTOizD4J$DRG 4A' @K \*F 4hp!%DPG =\{!2@69a" DXa4Q7 cz,"Dp D1 TcD = L "Dr@D 8sCx"Crhb5: V`j"ap> @T>D!m @!{FA#N|@,tSF>E!el+`|;z"Úq KN, T10>`TVB\Zd}Cp !7(b*#[ >,(b/D>$`p+@>@$HXQDL"6eD8`61 Ǹ: {H\1 BHS ! ,tBL=  hSB 5qP@ K !*G`gl b. W>EHiA=@T : lEr 1ՅHh !4 i@Xbh>1L(!xW%5v&` :C\cd0ȻQ=hD|1U A j"{ m4 3PK1Eap} H-Cț }a PWAY3Ÿ<"XtN"`8 )P_P> TT4C8` Hso hœT =&^PQUV{*€lz)a^0DЍBLUN#Ǹ*kEm,& cdi h35 5FP=@8l 4P CU H%8|qpTr`f?u*jA(~ !T@!8 !\n hm"` `Pϡ`AP0 a!>稤AA4aBA<B M  `rR$`* 8~iX!^aX ap!|`4`  vji" `  af & aXaa\ a."0AVP P n `>ts!xhA*`ּ@ FtA$>a$&AK`L,Ma a0`M@ 6R!`!<`*JADt~ Fad 6.|X 0^AdNq!Ttl a6H!   05 av<Q$P8&avV`ζa V6aHCD8 lK E`*0! "F(:u@2 ` `H4 J< ep1;a`c&&!%.2`fA`~adAa a`jzn ), `@2+fSJAn<$}+ `*As!fAT @%@<݊@w @G4er m !`"OP"z TA2 \  5@( @ A(4" endstream endobj 12 0 obj <> endobj 104 0 obj <>stream @@ &)̜e; S!4 8|@e'ىi|1:hI @ R+Eba p<&sA@1D#ȂP Hml Z̧c) 7 г E-x@LLCI{6o &3D ,!Ċr#BAԒv%$y1OFHy|I"!ƶG@1(EdYEdI.AcN@A#9 Q>D_BP^FLAH}ÐWU Ǹ}}#hY%nМ$C\B,PV5Gxaa.dE XbE2f=C "0> 4J O Q$V/\AU*CC{A 9mH 5@T&bi '؋ ~B 58 aExU*CHih\  \1;8}**@0 C^QPb /8-W0, DUZPo`k[`8> p*:cPy*`lOA.\(/&N/ -tqT=!>,Fp EhA}1V E %X!Rv$%@BLZH#+oVJi,} HB;h9b V#S,M !<%h < E`"РJ=` 450p B7"` 7 4Xoaepж![ljp5aE#è -`"0[`xKfXAi a8,bzaPaF~C FP5@[k|B VGm!p @pB|E@8 ? {aL < :pQ | DXlK>(E6_0>)(|WsqZ\ A9 A DؖQNOq"Ef=JΎgzzh &s`BX8 FaZp!Li@*J !a A,P`  NA `  <@r @,4ga`!@P>P HaZXH!Jǘ <@   fgz! A`D !<`!F r@, D +6> дkJkN+V^+f8 Ii AF!j&m!.& AAn!iw faRj` @8f!J a0k`m @hN a(o*z6 }A!  & a"@m2Ra% 7&X`aAa`!$#+ D °<a!(<4ǂg ̆ @JfAf@F:sv6k`(   ! Pa*c9!F`0!dA< !"0a2 !f*u aNS  @1-!@ TaaBJS:eƟLr `*!FZff ~@` `fF206=Na\!J` @ s t rz@< aTabg*y@cLaja@5^!2&!*]AcH}aj}8A2A A^!0^A ` : FA58ZҌj$2G$  A<a y6ee\`HN CA:s:`+u,A8!.aW3?@Aap!8 (tav t!3(@ UPj} `Z.A Da\gRB8Bi\`C"%z Ķh 8AVA~a4a ?rj ! A:`jFA viCaThA*"m 7(NbAܠ4AEB` a"w6m ʣRo @`` ` @ka NJ`E^AK@UP/`+xDE`n-arH!'. Dܨ`/@ӆ ` r 6 ` `JXXaz@< yT1LA&LT`4'h8anjJ z8v H @#f(2!h:0\z`lthZ* ` ^ a t ab Ad >  n tA xa"A+DgeP& ~0!]쭒( @m kr P"A`}B bp~)}n඘A& 4Ft!oaAnAB: `H h   @Ox\P`t\ N̾nAnX#ZA!q&! (ɫa daAaxapD.렘4` A Za*DATANsZ:`F@*@,` " `7b0T@Ba<tx !:! H @4 !XA Jv$RC ApAt\A"> &ApDA`  ȴ! @ f D@A,D€,@*A<``\ ^t 9}O:{^h n}BxEeZxO SGqJO,b‹vGء)}fة,} ZUgv@_KGFMkqM>ϕUe95}`sA{opK |0j7I#-}̀/UT9($ b?@tY/ 7F3$Z€#ITQBQHB8p)hm{4/sΎ?p`VaJcDjGZrRLaY| * X#BPS"|%{Aa37 00 [D֭d1@<$z48X"*0 @/Qn[an[ %pX|EPOEݞ\7hAD],@é'Tظ5#(6}|}A~&Y>g, F8b2# B|(%!x2Á`>Ѣ#YP%!&JdY&EABB`BΑ %nNjE4`ɒZ&ypZ1^A67T{'ؾUAQ@LQ ӗ9.?c^7: Cq%2)$AR8cX9C8bF`NY&Xf5PxȋW 5UElWl4WY'Ou jB "Jf|7C8}`F$D ~1 9f?)>|51,DQEdA,BBPޞM~7Ea P=(Kx>@#{15ce%ь&Do}b6D(,!`@S,=FYB&ȗnF9\?#rDX)hdvXy,j(ERq:R}c*b4F)q\" @퇠`T 5'XOC3>>A!FV0iIz)@L}0>x EX(Ж"4H0#Ќr#z!P{A:hF2DȘH .dg`Hi;F A(>ЦiŸ͌2k]_gB*! */ <&lP $'زA'Jfcp# 8HSt(D@HX*A "?Z dK#a!H2@}Ch &Ce }2@Ag0D@",6!0}`}!G b HX(Д8F$g^Z> sp2 M5jEtENP0 p>pbP CO”RGV=(4D|CH$A$uTR !0t p*lw@oAGlp`Be x-.ر]QeXzWK7t3RiM-4֜ڃ bBhjǸ zGh`Tp 0ma ڛX!%pb=l ~}t&%==0?H]c5C@i0֘bXj,u: \P+";Cu.A&&FP TA4@c4z_Y H)E\= <QA6+ `+hatA 0 t .u]1%aD(4{H"B {R8ٻpaE.cC!6$rQF_#4Ukb0WaA-Q dSF=rFG_*XI !Ah1e^T=Xxg̗BG@p=7@,8@'XO(]OpK/`XV`dh endstream endobj 76 0 obj <> endobj 105 0 obj <>stream @@ &9g9JFS9a9AGl,mPTtI=@ ȠR+Eba p<&sA@1D#ȂH C)Φn fSO6MBqb:y &"qXw`%c`Y|;ٓZ[Gh| ૬ J$)H}ǔ}J!IDd\p:JoЈ#y)K-y88| S/paL-K@Z` endstream endobj 15 0 obj <> endobj 106 0 obj <>stream @@NF TAï>0sTOqI, ȠR+Eba p<惠b9 Gq:Sn FS?6MBqb:3 Lsr6m0{ؐqDP&$QDl@ p% endstream endobj 8 0 obj <> endobj 107 0 obj <>stream @@  &)̜e; S& q36|O 7> :&'@`pH > l!88ܢcJEqHV,!h:#yRitX k1e6T:b:(o )l0_$TA7F Z"H"1̎t$I'bQK<4d9DR4ECYTV6#!jF: ǩ$R@jX\_FQ`t J @L `N#A@*H+P+X,!h- "x#X @`hp ; 2` <  |(Bh*(k# CjbhgIX K 1D)}"QAmcPzR(>P` { e$$E0&d`((w(*z,E.b03p2% 4C4@E`6c`6l88>:1:\0<5ŀ>?@F@y B!B*#0B>%D p|Y>{ +G$jdif }%a0=dH2<<c0Sq2Hr{ )MŠVKE9DEa&J{}(|Y4|Fm縈odJ-b>8>A4xKex{9v\$Yݗ$#/&гy'-^zt.ЖFDT`eQ>>@M!0|*>xD"à<>(`0`8b 4$`0 0 N># GU@CwǸ}mDG&"BX7=@C 'CL"qA="8(?/[xV!J> `{a`\e>AxX,C!:s@\ 9@Qoa. XA(<@8 88cHP Z+X,]nElS.ؿJ1A1`"hX @4= 29bC 1Pb14"¨v :Iwah>AWEP !(&L69= |F"SP9G 0p}#c{|k|?*75C/p0a~ƌ] l q<@ r}4/Pb,9!@BMQ8"ijf"ĭ" Ȃ.H}""pBx@``mFר5޸VsvD; )E n>#G ^@ TApC=""H6D\`EFB(M E"p) p9(rEr2y"X ,),B 7GC|b ŘaM<E/aN:Gm"|Va(IHEGv+D |~ b`)8 tz(wcyǸ0_`QBC@~ pTb\Qx۟ah 0x{b>$IPv9|A=@(q(P^ 1>'L@0 #d28uΉI9'c|h+`@TE0 X9"Ǡ# f a`9\lAƀ"}݂(#hB K. TU a&-a]E5 \ (hԹcT'R p$(c~V<> 6@ɰ@C$3ARne!"p &/38 * qŨ@p>b?CjE%C b; 3^ Tp TFղlXql-2 +#߰ G ;Ћ "@B ! #K_7]0~ !C0CxN|Y )Ĉ8 ` `bHFF `ntiv$u*!G(max `yaA4azVz" !,6-'va4N"  4t|G2v`v JN8P Pa#p*xpF2azeja8z`t!! >BA|!!X*  !AH!  8` 6 aV a `> 2 B<HADЊa0$^`2!D̀& L:aa!zaX ^x ``2aTrR dJha˨a؀@ !.`l/*A(B > ``n!NnBaaxd S%` a a!$ 4 & ͂ `N`!L >`a!\a\zx0!T!~`'`&@**A<@ ` a R ba~<q2 !d!<x<!4as+,KHaT!,q6`n @Tm/ĭA Aa CCDtJʹP tB4'BB2ߧ>J^!*LAu&* r!`d!@2! '> 0 v j&F2 >v daLal >,2D@ @g5A6-nhmrN2& l txi3V5M! Pa.  5ʫ4$4`!!r`0  5a"a$ (P"AS]'F TATaA4&h H`` &g !h 4]'YA8>HDNH@0!la0qAC\uBU > $``` "!!*qA@&}]`]D!'6a. & a0Jo  ,(af0j ?tt! TFAX  P.`a~PF^ < v @>D>!A A$$V!fL l`  Ԙ n h~<a0 6pa\8 `^/:` ^w` Z>\^rݡ<5J-!*+>! bN 'd!-dt& .9<FznJAqTSr! *`h) A 6a2ǞfX@,p86 nv 1xL!6a5U݊+&  >qWv$u `!`@.؉ƾ#! A' o"A0>AFO_A AJ`Ȁ@ZƧZ. @ ` `!fˁ6a LP`~ N < At~!z` `r AHMA E&!Ml @ ,0">x!2Q]%,754\{ZtN ua6SA TaPg65p!4Al`PAJ8&@1_4 N !6 @ /1qA!!nz  AVAjva \XV aP!Hva* ` AA0> `@+D`@n @ @> `xs,Oapa6A^Ly|!!IT: 18D!r!0H` A0eaGp̆G6@  tw'P"@  ! gb ! !-a`:aA4ԍtJjβzs N `A;Gv Kp m)& (AZU ppA v~xx i`>XTGT* a22cW|5+@srNR4A2af v H\@8!1y=  ҄^$ x P !bX!z/!PAV ^ @ ` @᐀rs<`jsAhj!*`F 0 }(jxA ac`` l)8A nW lAr!^ a ATa  q l Q]rjx"4[NZ %BEw -48/U{TbLMl@"$uD/IұqK3:(vۯpB@hpAM(Y=pp`"u X'{{{B3cܼ[T)Jl)UWlZ8* kq[}4AP(!E4<=Չ8|LڀSS$Jgm\ }F#N!nb=JGd8V™N| G0 AEpI08 8p!aL2P><#BP?\P;h;5c0+"k%)j_ʼnTNdYbEG`" hJdOqLIQ$ELDXe4UaNMYzE1D>`AB*V ^"1X? ~2`(f(DIz 9\\E(6`:424 xfoQ3 ^ ||'fpv[GLrYibs!.`bnv!Ɍ%ŐU] h{h)`H|lE#\6"Vta (.: XEUwIuih\tP֎ق'$Ǹb{`j\$d "ش߈(4,*BdY`90!Р0bx CH9b  =y0lIc>~ mBB8H$ʌ!z|KxěNO,Ji1qL$XSe)S ` !àE#Г:BL`$X ="Paa\E= Pa_!HD~E0]@& "@t¤} (MLдL6[ ,E`n#A(a` !j,FH3<*X"l(HȪ=&FQ<NQ@w 2@˃0M4#"J?y 9!D}a$yNԋDBCX{!5Ǹ"$,RZ,EtCZ$'CQ" 6Ca.P9$W,P@{ ?Euu 3P9!4F& )D-o¸ ?Yø b4\GL}!hb8D& Dpu|A! x,M`#` "}Hfr*Bad"tA C= 70߃k>q>Df~s=,K%@@a &èQ5qCml%DXZa]V!8-Pߍ1,%ؒcWA!DIfqF9k ,P\O *B&**d&DЮ( P |>AQ, ! !'^oaBG' V=0j Q2^ȕb4G&X^2E2(~ 1qǸrV .vL8ZLy|+#alq$s}LE5YҀ|-ȷ~#D;Q a8@!oœ| P{B`|($*E| A:T )<qK o,FV1V8> !`8 "*18 kq#Bx "*>&ҚX}4K֞Q"ð"7">>t _"PQ=XBT`1'͠BTA v+¹r!([\2$Ȣ$v4E V =pcvn8Sq.P`atGFZX{Iżu% Pĸ;@[hm(ZZ)pE=7P;</hR`nXax,=X38'CZ\`ef/`3396h7#A{8eRŃ (|/ g'X{@x{x $X#܄!(XbҨh8$m{pIrA>@2S})}EHEPEH 0G@IXY ?83&X'>6QJ0r29oSK\b@a\^[Q(hY* |( pV84/@94\LHF`HIhEXFIB5x33{(_!IMJ0EH N9}@ UmWՍYըT^V|eZ\p(쇸] 63"49h}XHq(ZR_[ P7p89p@AALSHSHTxi* fS-Xܸ]HR\qqP3`18+X?  @SQ@KX'x&h3(}h>H`5/T-AmhYHo" 4?@N{txt c^g0jN8&P$ЅT(hHf*0 ~B$h44H+6i&`Y^SVҸoH7 s <}{}h}}}x}}ڀV{hLv)D9H2H-(.'07@3V`^hXSXWQ̄- FFH <:?MON8H@L0L?pB3D SP 6?%P+~I2y'hA SIL `R@QM>?Xh:BERQPHGK?p=;>;GH56;(PMPWQI؋ =9>AX TOK 9B=ELPJO@VHIJHpPX}RJ k8_ P=H8ULX(R3:yb+.b{hf9O}x$},oo8Jy݄=-Y H0}:LȕZPpXT`ph endstream endobj 2 0 obj <>endobj xref 0 108 0000000000 65535 f 0000061808 00000 n 0000281327 00000 n 0000061629 00000 n 0000058869 00000 n 0000000015 00000 n 0000004735 00000 n 0000256035 00000 n 0000269860 00000 n 0000254722 00000 n 0000256606 00000 n 0000255113 00000 n 0000260393 00000 n 0000255817 00000 n 0000255879 00000 n 0000269350 00000 n 0000061856 00000 n 0000059011 00000 n 0000004755 00000 n 0000008523 00000 n 0000061928 00000 n 0000059155 00000 n 0000008544 00000 n 0000014063 00000 n 0000061991 00000 n 0000059299 00000 n 0000014084 00000 n 0000019537 00000 n 0000062032 00000 n 0000059443 00000 n 0000019558 00000 n 0000023996 00000 n 0000062073 00000 n 0000059587 00000 n 0000024017 00000 n 0000028051 00000 n 0000062114 00000 n 0000059731 00000 n 0000028072 00000 n 0000031553 00000 n 0000062155 00000 n 0000059875 00000 n 0000031574 00000 n 0000035510 00000 n 0000062196 00000 n 0000060019 00000 n 0000035531 00000 n 0000039844 00000 n 0000062237 00000 n 0000060163 00000 n 0000039865 00000 n 0000041459 00000 n 0000062278 00000 n 0000060307 00000 n 0000041480 00000 n 0000043298 00000 n 0000062351 00000 n 0000062319 00000 n 0000098040 00000 n 0000060475 00000 n 0000043319 00000 n 0000044951 00000 n 0000098113 00000 n 0000098081 00000 n 0000134174 00000 n 0000060643 00000 n 0000044972 00000 n 0000046069 00000 n 0000134247 00000 n 0000134215 00000 n 0000149378 00000 n 0000060811 00000 n 0000046090 00000 n 0000049128 00000 n 0000149440 00000 n 0000255651 00000 n 0000268719 00000 n 0000149408 00000 n 0000170113 00000 n 0000060979 00000 n 0000049149 00000 n 0000054105 00000 n 0000170197 00000 n 0000170165 00000 n 0000203595 00000 n 0000061147 00000 n 0000054126 00000 n 0000054346 00000 n 0000215468 00000 n 0000203679 00000 n 0000203636 00000 n 0000224184 00000 n 0000061315 00000 n 0000054366 00000 n 0000054588 00000 n 0000240003 00000 n 0000224257 00000 n 0000224214 00000 n 0000254650 00000 n 0000061483 00000 n 0000054608 00000 n 0000058847 00000 n 0000254680 00000 n 0000256924 00000 n 0000260826 00000 n 0000268972 00000 n 0000269590 00000 n 0000270466 00000 n trailer << /Size 108 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 281548 %%EOF iozone3_488/docs/Run_rules.doc0000644000175000017500000006400013573734166015461 0ustar cappscappsࡱ> /1.G &bjbjَ *&]  { } } } } } } $l `  .{ { &{ @ c Iozone run rules In order for Iozone results to be comparable, it is important that some basic rules be followed. The idea is that someone should be able to reproduce the same results given this report. The following is a list of rules. For buffer cache performance comparisons: For single stream results, be sure the file size is smaller than the buffer cache. For throughput results, be sure the aggregate of files is smaller than the buffer cache. The file size must also be at least 3 times the size of processor cache for both internal and external processor caches. For disk performance comparisons: For single stream results, be sure the file size is 3 times the size of the buffer cache. For throughput results, be sure the aggregate of files is 3 times the size of the buffer cache. For automatic mode (-a) Be sure that the buffer cache is less than or equal to 128 Megabytes. The benchmark will automatically start with small file sizes and increment up to 512 Megabytes. This will ensure that the results contain both in and out of buffer cache results. For NFS results: When publishing results for NFS, the system specification described below expands to include the complete hardware and software disclosure of all networking components and load generators. System specification disclosure: Report must include: Number of cpus in the system Total amount of memory in the system Total amount of buffer cache in the system Total number of disks in the system Complete description of the layout of the disks in the system Type of cpu, clock speed, processor cache sizes, external cache sizes Type of disk controllers Number of disk controllers Type of disks If using striping, include a complete description of the stripe layout Complete command line that was issued with Iozone for the given result. Version number of Iozone used for the tests. Version of the Operating system Availability dates of all software and hardware used. Type of filesystem being used. Total amount of NVRAM in the system. (including the disks, disk controllers) Date when tested. Any other hardware used in the test. Raw Iozone output file with the -R option enabled. Filesystems under test must have been cleaned (freshly created) before the test began. Minimum results include results for: Read, Write, Re-read, Re-write, Backward read, Strided read, and Random read. The results for mmap, threads, and async I/O are optional as not all vendors support everything that Iozone can test. Compiler options used to compile Iozone. Options used to create the filesystems. Options used to mount the filesystems. List of all tunables that were applied to the system. Company name if publishing for a company. Name of the person that ran the benchmark and their email address. Other requirements: The benchmark may not be modified. You may use any compiler options you wish. Any tuning that is done that benefits only this benchmark is not permitted. This includes special tunables in the operating system, or any commands or utilities that are used to enhance the results of Iozone and are not used for real customer needs. When running Iozone in any mode that is attempting to flush the data to disk, the data must make it to stable storage (where stable storage is defined to be: Data written is recoverable for a period of at least one week of power outage.) Use of hardware or software that is not available for purchase within a 6 month time period is not permitted. Use of hardware/software that will not be available for at least 6 months after publication is not permitted. The system under test must be in multiuser mode with all daemons that would normally be running. Review of results: Unlike other benchmarks, there is no review required for the results to be accepted. There are several reasons why this is not needed. We are all gentlemen and ladies and always act professionally. We all respect the golden rule and treat others as we would like to be treated. If you lie or cheat, you will only discredit yourself and your company. There is no way you won't get caught. The benchmark is publicly available for free. Your customers will download it and check the platform before they accept the machine or pay for it. If your company publishes bogus results that can not be reproduced, this may be interpreted as false advertising. Who knows, it may even get your company a nice lawsuit from a competitor. In general, if you feel guilty about your results, then don't make them available for others to see. Hostile publications: In these times of road rage, sometimes people will publish negative results about a product that are not true. In the event that any company or product has been attacked with bogus results, the company may run the benchmark themselves and publish correct results. The incorrect results may not be removed, but the new results will be added. In the event that a publishing conflict continues, the webmaster of the results page maintains the right to delete inaccurate hostile results from the archive. In the event of hostile floods, the webmaster of the results page reserves the right to block further publications from the person/company that is continuing the abuse. Any person/company that believes their product is being slandered is free to pursue the person/company for damages. The Iozone webmaster, authors, site owners, and friends are not liable for hostile publications. The Iozone results web page is like a chalkboard in the hallway of the internet. The maintainers reserve the right to remove graffiti, but are not responsible for what people may write on it. Web rules: The webmaster of the results page reserves the right to block publication of results if the intent of the publication is hostile. Hostility may take many forms. Publication of results that are known to be inaccurate, floods of publications in an attempt to overload the web site, publication of results that contain viruses are a few examples. If the webmaster perceives the intent to be hostile in nature, the publication may be refused. The webmaster reserves the right to control the submittal and publication process. Ce!96G % i}&5CJ$5CJ$BCef !9:56G  ' ( > [  & F & F & F  & F & F & F$BCef !9:56G  ' ( > [ S l $ Q q  % J } ý{u                                                             + S l $ Q q  % J } 7m & F & F 7m@<*hi|}ER#$%&                                                     %@<*hi|}ER#$%& & F & F/ =!"#$% [$@$NormalmH <A@<Default Paragraph Font&*& & &l q C K (X e ! )   = K ntnu(/n( Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.docJCapps'C:\TEMP\Iozone comparison run rules.doc Don Capps*C:\DATA\MS\Iozone comparison run rules.doc Don Capps.\\RSNPERF\CAPPS\iozone_run_rules\Run_rules.doc ?M  (T c- @ 'OW Xf y: !dz hho(.hho(.hho(.hho(.hho(.hho(.hho(.o(.hho(. Xf'OW?Mc-y !dz(T@ @@&P@GTimes New Roman5Symbol3& Arial"phr9Fr9FB9f~ *20dsIozone comparison run rules Don Capps Don Capps Oh+'0  8 D P \hpxIozone comparison run rulesozo Don Cappspaon  Normal.dota Don Cappsa2n Microsoft Word 8.0u@F#@^@M@M~ ՜.+,D՜.+,T hp  Hewlett-Packard* sj Iozone comparison run rules Title 6> _PID_GUIDAN{89D73AC5-56F0-11D3-A7C6-0080C789BADA}  !"#$%'()*+,-0Root Entry F&21TableWordDocument*SummaryInformation(DocumentSummaryInformation8&CompObjjAqA$A  FMicrosoft Word Document MSWordDocWord.Document.89qiozone3_488/docs/IOzone_msword_98.doc0000744000175000017500000064000013573734166016622 0ustar cappscappsࡱ> y )bjbj ~{{Cll222FFFF,rF:4+++\:^:^:^:^:^:^:$<>R:2+c'x+++:U:999+2\:9+\:999 : @,1.:H::0::?7? :?2 :(++9+++++::9+++:++++?+++++++++l : Iozone Filesystem Benchmark IOzone is a filesystem benchmark tool. The benchmark generates and measures a variety of file operations. Iozone has been ported to many machines and runs under many operating systems. This document will cover the many different types of operations that are tested as well as coverage of all of the command line options. Iozone is useful for determining a broad filesystem analysis of a vendors computer platform. The benchmark tests file I/O performance for the following operations. Read, write, re-read, re-write, read backwards, read strided, fread, fwrite, random read/write, pread/pwrite variants, aio_read, aio_write, mmap, While computers are typically purchased with an application in mind it is also likely that over time the application mix will change. Many vendors have enhanced their operating systems to perform well for some frequently used applications. Although this accelerates the I/O for those few applications it is also likely that the system may not perform well for other applications that were not targeted by the operating system. An example of this type of enhancement is: Database. Many operating systems have tested and tuned the filesystem so it works well with databases. While the database users are happy, the other users may not be so happy as the entire system may be giving all of the system resources to the database users at the expense of all other users. As time rolls on the system administrator may decide that a few more office automation tasks could be shifted to this machine. The load may now shift from a random reader application (database) to a sequential reader. The users may discover that the machine is very slow when running this new application and become dissatisfied with the decision to purchase this platform. By using Iozone to get a broad filesystem performance coverage the buyer is much more likely to see any hot or cold spots and pick a platform and operating system that is more well balanced. Features: ANSII C source. POSIX async I/O. Mmap() file I/O. Normal file I/O. Single stream measurement. Multiple stream measurement. POSIX pthreads. Multi-process measurement. Excel importable output for graph generation. I/O Latency data for plots. 64-bit compatible source. Large file compatible. Stonewalling in throughput tests to eliminate straggler effects. Processor cache size configurable. Selectable measurements with fsync, O_SYNC. Options targeted for testing over NFS. Building IOzone Once you have obtained the source for IOzone you should have 12 files. iozone.c (source code) libasync.c (source code) makefile (makefile) libbif.c (source code) Iozone_msword_98.doc (documentation in Word format) iozone.1 (documentation in nroff format) gnuplot.dem (sample gnuplot file ) gnuplotps.dem (sample gnuplot file that generates postscript output) read_telemetry (sample file for read telemetry file) write_telemetry (sample file for write telemetry file) Run_rules.doc (run rules to get reasonable results) Changes.txt (log of changes to Iozone since its beginning) Type: make The makefile will display a list of supported platforms. Pick the one that matches your configuration and then type: make target Thats it. Youre done. There is no need to have any install procedures as IOzone creates all of its files in the current working directory. Just copy Iozone to wherever you wish to test the filesystem performance and then run it. Or you can use the f command line option to specify a target path, for example, a path/filename in a new filesystem. Before you run Iozone please read the run rules at the bottom of this document. Examples of running Iozone: The simplest way to get started is to try the automatic mode. iozone a If you wish to generate graphs then you may wish to turn on Excel mode. iozone Ra ( Output can be imported using space and tab delimited) Or iozone Rab output.wks ( Output file output.wks is a binary format spreadsheet) If you have more than 512 Mbytes of memory then you need to increase the maximum file size to a larger value. For example if your system has 1 Gbyte of memory then you would want to try something like: iozone Ra g 2G If you only care about read/write and do not wish to spend the time to perform all of the tests, then you may wish to limit the testing like: iozone Ra g 2G i 0 i 1 If you are running Iozone over NFS on an NFS client then you may wish to use: iozone Rac This tells Iozone to include the close() in the measurement. This may be needed if the client is running NFS version 3. Including the close() helps to reduce the client side cache effects of NFS version 3. If you use a file size that is larger than the amount of memory in the client then the c flag is not needed. Definitions of the tests Write: This test measures the performance of writing a new file. When a new file is written not only does the data need to be stored but also the overhead information for keeping track of where the data is located on the storage media. This overhead is called the metadata It consists of the directory information, the space allocation and any other data associated with a file that is not part of the data contained in the file. It is normal for the initial write performance to be lower than the performance of re-writing a file due to this overhead information. Re-write: This test measures the performance of writing a file that already exists. When a file is written that already exists the work required is less as the metadata already exists. It is normal for the rewrite performance to be higher than the performance of writing a new file. Read: This test measures the performance of reading an existing file. Re-Read: This test measures the performance of reading a file that was recently read. It is normal for the performance to be higher as the operating system generally maintains a cache of the data for files that were recently read. This cache can be used to satisfy reads and improves the performance. Random Read: This test measures the performance of reading a file with accesses being made to random locations within the file. The performance of a system under this type of activity can be impacted by several factors such as: Size of operating systems cache, number of disks, seek latencies, and others. Random Write: This test measures the performance of writing a file with accesses being made to random locations within the file. Again the performance of a system under this type of activity can be impacted by several factors such as: Size of operating systems cache, number of disks, seek latencies, and others. Random Mix: This test measures the performance of reading and writing a file with accesses being made to random locations within the file. Again the performance of a system under this type of activity can be impacted by several factors such as: Size of operating systems cache, number of disks, seek latencies, and others. This test is only available in throughput mode. Each thread/process runs either the read or the write test. The distribution of read/write is done on a round robin basis. More than one thread/process is required for proper operation. Backwards Read: This test measures the performance of reading a file backwards. This may seem like a strange way to read a file but in fact there are applications that do this. MSC Nastran is an example of an application that reads its files backwards. With MSC Nastran, these files are very large (Gbytes to Tbytes in size). Although many operating systems have special features that enable them to read a file forward more rapidly, there are very few operating systems that detect and enhance the performance of reading a file backwards. Record Rewrite: This test measures the performance of writing and re-writing a particular spot within a file. This hot spot can have very interesting behaviors. If the size of the spot is small enough to fit in the CPU data cache then the performance is very high. If the size of the spot is bigger than the CPU data cache but still fits in the TLB then one gets a different level of performance. If the size of the spot is larger than the CPU data cache and larger than the TLB but still fits in the operating system cache then one gets another level of performance, and if the size of the spot is bigger than the operating system cache then one gets yet another level of performance. Strided Read: This test measures the performance of reading a file with a strided access behavior. An example would be: Read at offset zero for a length of 4 Kbytes, then seek 200 Kbytes, and then read for a length of 4 Kbytes, then seek 200 Kbytes and so on. Here the pattern is to read 4 Kbytes and then Seek 200 Kbytes and repeat the pattern. This again is a typical application behavior for applications that have data structures contained within a file and is accessing a particular region of the data structure. Most operating systems do not detect this behavior or implement any techniques to enhance the performance under this type of access behavior. This access behavior can also sometimes produce interesting performance anomalies. An example would be if the applications stride causes a particular disk, in a striped file system, to become the bottleneck. Fwrite: This test measures the performance of writing a file using the library function fwrite(). This is a library routine that performs buffered write operations. The buffer is within the users address space. If an application were to write in very small size transfers then the buffered & blocked I/O functionality of fwrite() can enhance the performance of the application by reducing the number of actual operating system calls and increasing the size of the transfers when operating system calls are made. This test is writing a new file so again the overhead of the metadata is included in the measurement. Frewrite: This test measures the performance of writing a file using the library function fwrite(). This is a library routine that performs buffered & blocked write operations. The buffer is within the users address space. If an application were to write in very small size transfers then the buffered & blocked I/O functionality of fwrite() can enhance the performance of the application by reducing the number of actual operating system calls and increasing the size of the transfers when operating system calls are made. This test is writing to an existing file so the performance should be higher as there are no metadata operations required. Fread: This test measures the performance of reading a file using the library function fread(). This is a library routine that performs buffered & blocked read operations. The buffer is within the users address space. If an application were to read in very small size transfers then the buffered & blocked I/O functionality of fread() can enhance the performance of the application by reducing the number of actual operating system calls and increasing the size of the transfers when operating system calls are made. Freread: This test is the same as fread above except that in this test the file that is being read was read in the recent past. This should result in higher performance as the operating system is likely to have the file data in cache. Specialized tests: Mmap: Many operating systems support the use of mmap() to map a file into a users address space. Once this mapping is in place then stores to this location in memory will result in the data being stored going to a file. This is handy if an application wishes to treat files as chunks of memory. An example would be to have an array in memory that is also being maintained as a file in the files system. The semantics of mmap files is somewhat different than normal files. If a store to the memory location is done then no actual file I/O may occur immediately. The use of the msyc() with the flags MS_SYNC, and MS_ASYNC control the coherency of the memory and the file. A call to msync() with MS_SYNC will force the contents of memory to the file and wait for it to be on storage before returning to the application. A call to msync() with the flag MS_ASYNC tells the operating system to flush the memory out to storage using an asynchronous mechanism so that the application may return into execution without waiting for the data to be written to storage. This test measures the performance of using the mmap() mechanism for performing I/O. Async I/O: Another mechanism that is supported by many operating systems for performing I/O is POSIX async I/O. The application uses the POSIX standard async I/O interfaces to accomplish this. Example: aio_write(), aio_read(), aio_error(). This test measures the performance of the POSIX async I/O mechanism. Command Line options: The following is the output from the built in help. Each options purpose is explained in this section of the manual. Usage: iozone [-s filesize_Kb] [-r record_size_Kb ] [-f [path]filename] [-i test] [-E] [-p] [-a] [-A] [-z] [-Z] [-m] [-M] [-t children] [-h] [-o] [-l min_number_procs] [-u max_number_procs] [-v] [-R] [-x] [-d microseconds] [-F path1 path2...] [-V pattern] [-j stride] [-T] [-C] [-B] [-D] [-G] [-I] [-H depth] [-k depth] [-U mount_point] [-S cache_size] [-O] [-K] [-L line_size] [-g max_filesize_Kb] [-n min_filesize_Kb] [-N] [-Q] [-P start_cpu] [-c] [-e] [-b filename] [-J milliseconds] [-X filename] [-Y filename] [-w] [-W] [-y min_recordsize_Kb] [-q max_recordsize_Kb] [-+m filename] [-+n] [-+N] [-+u ] [ -+d ] [-+p percent_read] [-+r] [-+t ] [-+A #] What do they all mean ? -a Used to select full automatic mode. Produces output that covers all tested file operations for record sizes of 4k to 16M for file sizes of 64k to 512M. -A This version of automatic mode provides more coverage but consumes a bunch of time. The a option will automatically stop using transfer sizes less than 64k once the file size is 32 MB or larger. This saves time. The A option tells Iozone that you are willing to wait and want dense coverage for small transfers even when the file size is very large. NOTE: This option is deprecated in Iozone version 3.61. Use az i 0 i 1 instead. -b filename Iozone will create a binary file format file in Excel compatible output of results. -B Use mmap() files. This causes all of the temporary files being measured to be created and accessed with the mmap() interface. Some applications prefer to treat files as arrays of memory. These applications mmap() the file and then just access the array with loads and stores to perform file I/O. -c Include close() in the timing calculations. This is useful only if you suspect that close() is broken in the operating system currently under test. It can be useful for NFS Version 3 testing as well to help identify if the nfs3_commit is working well. -C Show bytes transferred by each child in throughput testing. Useful if your operating system has any starvation problems in file I/O or in process management. -d # Microsecond delay out of barrier. During the throughput tests all threads or processes are forced to a barrier before beginning the test. Normally, all of the threads or processes are released at the same moment. This option allows one to delay a specified time in microseconds between releasing each of the processes or threads. -D Use msync(MS_ASYNC) on mmap files. This tells the operating system that all the data in the mmap space needs to be written to disk asynchronously. -e Include flush (fsync,fflush) in the timing calculations -E Used to select the extension tests. Only available on some platforms. Uses pread interfaces. -f filename Used to specify the filename for the temporary file under test. This is useful when the unmount option is used. When testing with unmount between tests it is necessary for the temporary file under test to be in a directory that can be unmounted. It is not possible to unmount the current working directory as the process Iozone is running in this directory. -F filename filename filename Specify each of the temporary file names to be used in the throughput testing. The number of names should be equal to the number of processes or threads that are specified. -g # Set maximum file size (in Kbytes) for auto mode. -G Use msync(MS_SYNC) on mmap files. This tells the operating system that all the data in the mmap space needs to be written to disk synchronously. -h Displays help screen. -H # Use POSIX async I/O with # async operations. Iozone will use POSIX async I/O with a bcopy from the async buffers back into the applications buffer. Some versions of MSC NASTRAN perform I/O this way. This technique is used by applications so that the async I/O may be performed in a library and requires no changes to the applications internal model. -i # Used to specify which tests to run. (0=write/rewrite, 1=read/re-read, 2=random-read/write 3=Read-backwards, 4=Re-write-record, 5=stride-read, 6=fwrite/re-fwrite, 7=fread/Re-fread, 8=random mix, 9=pwrite/Re-pwrite, 10=pread/Re-pread, 11=pwritev/Re-pwritev, 12=preadv/Re-preadv). One will always need to specify 0 so that any of the following tests will have a file to measure. -i # -i # -i # is also supported so that one may select more than one test. -I Use DIRECT I/O for all file operations. Tells the filesystem that all operations are to bypass the buffer cache and go directly to disk. This also will use VX_DIRECT on VxFS, and O_DIRECT on Linux, and directio() on Solaris. -j # Set stride of file accesses to (# * record size). The stride read test will read records at this stride. -J # (in milliseconds) Perform a compute delay of this many milliseconds before each I/O operation. See also -X and -Y for other options to control compute delay. -k # Use POSIX async I/O (no bcopy) with # async operations. Iozone will use POSIX async I/O and will not perform any extra bcopys. The buffers used by Iozone will be handed to the async I/O system call directly. -K Generate some random accesses during the normal testing. -l # Set the lower limit on number of processes to run. When running throughput tests this option allows the user to specify the least number of processes or threads to start. This option should be used in conjunction with the -u option. -L # Set processor cache line size to value (in bytes). Tells Iozone the processor cache line size. This is used internally to help speed up the test. -m Tells Iozone to use multiple buffers internally. Some applications read into a single buffer over and over. Others have an array of buffers. This option allows both types of applications to be simulated. Iozones default behavior is to re-use internal buffers. This option allows one to override the default and to use multiple internal buffers. -M Iozone will call uname() and will put the string in the output file. -n # Set minimum file size (in Kbytes) for auto mode. -N Report results in microseconds per operation. -o Writes are synchronously written to disk. (O_SYNC). Iozone will open the files with the O_SYNC flag. This forces all writes to the file to go completely to disk before returning to the benchmark. -O Give results in operations per second. -p This purges the processor cache before each file operation. Iozone will allocate another internal buffer that is aligned to the same processor cache boundary and is of a size that matches the processor cache. It will zero fill this alternate buffer before beginning each test. This will purge the processor cache and allow one to see the memory subsystem without the acceleration due to the processor cache. -P # Bind processes/threads to processors, starting with this cpu #. Only available on some platforms. The first sub process or thread will begin on the specified processor. Future processes or threads will be placed on the next processor. Once the total number of cpus is exceeded then future processes or threads will be placed in a round robin fashion. -q # Set maximum record size (in Kbytes) for auto mode. One may also specify -q #k (size in Kbytes) or -q #m (size in Mbytes) or -q #g (size in Gbytes). See y for setting minimum record size. -Q Create offset/latency files. Iozone will create latency versus offset data files that can be imported with a graphics package and plotted. This is useful for finding if certain offsets have very high latencies. Such as the point where UFS will allocate its first indirect block. One can see from the data the impacts of the extent allocations for extent based filesystems with this option. -r # Used to specify the record size, in Kbytes, to test. One may also specify -r #k (size in Kbytes) or -r #m (size in Mbytes) or -r #g (size in Gbytes). -R Generate Excel report. Iozone will generate an Excel compatible report to standard out. This file may be imported with Microsoft Excel (space delimited) and used to create a graph of the filesystem performance. Note: The 3D graphs are column oriented. You will need to select this when graphing as the default in Excel is row oriented data. -s # Used to specify the size, in Kbytes, of the file to test. One may also specify -s #k (size in Kbytes) or -s #m (size in Mbytes) or -s #g (size in Gbytes). -S # Set processor cache size to value (in Kbytes). This tells Iozone the size of the processor cache. It is used internally for buffer alignment and for the purge functionality. -t # Run Iozone in a throughput mode. This option allows the user to specify how many threads or processes to have active during the measurement. -T Use POSIX pthreads for throughput tests. Available on platforms that have POSIX threads. -u # Set the upper limit on number of processes to run. When running throughput tests this option allows the user to specify the greatest number of processes or threads to start. This option should be used in conjunction with the -l option. -U mountpoint Mount point to unmount and remount between tests. Iozone will unmount and remount this mount point before beginning each test. This guarantees that the buffer cache does not contain any of the file under test. -v Display the version of Iozone. -V # Specify a pattern that is to be written to the temporary file and validated for accuracy in each of the read tests. -w Do not unlink temporary files when finished using them. Leave them present in the filesystem. -W Lock files when reading or writing. -x Turn off stone-walling. Stonewalling is a technique used internally to Iozone. It is used during the throughput tests. The code starts all threads or processes and then stops them on a barrier. Once they are all ready to start then they are all released at the same time. The moment that any of the threads or processes finish their work then the entire test is terminated and throughput is calculated on the total I/O that was completed up to this point. This ensures that the entire measurement was taken while all of the processes or threads were running in parallel. This flag allows one to turn off the stonewalling and see what happens. -X filename Use this file for write telemetry information. The file contains triplets of information: Byte offset, size of transfer, compute delay in milliseconds. This option is useful if one has taken a system call trace of the application that is of interest. This allows Iozone to replicate the I/O operations that this specific application generates and provide benchmark results for this file behavior. (if column 1 contains # then the line is a comment) -y # Set minimum record size (in Kbytes) for auto mode. One may also specify -y #k (size in Kbytes) or -y #m (size in Mbytes) or -y #g (size in Gbytes). See q for setting maximum record size. -Y filename Use this file for read telemetry information. The file contains triplets of information: Byte offset, size of transfer, compute delay in milliseconds. This option is useful if one has taken a system call trace of the application that is of interest. This allows Iozone to replicate the I/O operations that this specific application generates and provide benchmark results for this file behavior. (if column 1 contains # then the line is a comment) -z Used in conjunction with -a to test all possible record sizes. Normally Iozone omits testing of small record sizes for very large files when used in full automatic mode. This option forces Iozone to include the small record sizes in the automatic tests also. -Z Enable mixing mmap I/O and file I/O. -+m filename Use this file to obtain the configuration information of the clients for cluster testing. The file contains one line for each client. Each line has three fields. The fields are space delimited. A # sign in column zero is a comment line. The first field is the name of the client. The second field is the path, on the client, for the working directory where Iozone will execute. The third field is the path, on the client, for the executable Iozone. To use this option one must be able to execute commands on the clients without being challenged for a password. Iozone will start remote execution by using rsh. -+n No retests selected. Use this to prevent retests from running. -+N No truncating or deleting of previous test file before the sequential write test. Useful only after -w is used in previous command to leave the test file in place for reuse. This flag is of limited use, when a single retest is not enough, or to easily control when sequential write retests occur without file truncation or deletion. -+u Enable CPU utilization mode. -+d Enable diagnostic mode. In this mode every byte is validated. This is handy if one suspects a broken I/O subsystem. -+p percent_read Set the percentage of the thread/processes that will perform random read testing. Only valid in throughput mode and with more than 1 process/thread. -+r Enable O_RSYNC and O_SYNC for all I/O testing. -+t Enable network performance test. Requires -+m -+A Enable madvise. 0 = normal, 1=random, 2=sequential, 3=dontneed, 4=willneed. For use with options that activate mmap() file I/O. See: -B What can I see: The following are some graphs that were generated from the Iozone output files.  From the graph above one can clearly see the buffer cache helping out for file sizes that are less than 256MB but after that the actual disk I/O speed can be seen. Also note that the processor cache effects can be seen for file sizes of 16 Kbytes to 1Mbyte.  The graph above is displaying the impact of re-reading a file. Notice that the processor cache is now very important and causes the sharp peak. The next plateau to the right is buffer cache and finally above 256MB the file no longer fits in the buffer cache and real spindle speeds can be seen.  The graph above was created by running Iozone multiple times and then graphing the combination of the results. Here the graph is showing the throughput performance as a function of processes and number of disks participating in a filesystem. (disk striping) The good news is that on this system as one adds disks the throughput increases. Not all platforms scale so well.  The graph above shows single stream performance where file size and request size are changed. The place on the lower right that touches the floor of the graph is not actual data. Excel graphs empty cells as containing a zero. This run was taken with the a option. If one used the A option then the area that was not tested would have been tested and had real values. Normally this is not a desirable area to test because it is very time consuming to write a 512MB file in 4k transfer sizes. The a option in Iozone tells Iozone to discontinue use of transfer sizes less than 64k once the file size is 32MB or bigger. This saves quite a bit of time. Notice the ridge that runs from the top left to the lower right down the center of the graph. This is where the request size fits in the processor cache. For file sizes less than the size of the processor cache you can see the rise in performance as well. When both the file size and the transfer size is less than the processor cache it rises even higher. Although interesting to see, it is unlikely that you will be able to get applications to never write files that are bigger than the processor cache ( However it might be possible to get applications to try to re-use buffers and keep the buffer size smaller than the processor cache size.   The graph above is an example of a real system with some interesting optimizations. Here one can see that there are some file sizes and some record sizes that have very bad performance. Notice the performance dip at record sizes of 128Kbytes. (Anomaly #1) There is also a dropoff for file sizes of 8 MB and larger. The dropoff for files greater than 8MB is very interesting since this machine has 16 GB of memory and an 8GB buffer cache. This is a classic example of tuning for a specific application. If the poor system administrator ever installs an application that likes to read or write files in a record size of 128 Kbytes to 1 Mbyte his users will probably take him out back for a conference. If the system would have been characterized before it was purchased it would never have made it into the building. Another type of graph that can be produced is the Latency graph. When the -Q option is used Iozone will generate four .dat files. Rol.dat, wol.dat, rwol.dat and rrol.dat. These are read offset latency, write offset latency, rewrite offset latency and reread offset latency. These files can be imported into Excel and then graphed. The latency versus offset information is useful for seeing if there are any particular offsets in a file that have high latencies. These high latencies can be caused by a variety of causes. An example would be if the file size is just a bit bigger than the buffer cache size. The first time the file is written the latency will be low for each transfer. This is because the writes are going into the buffer cache and the application is allowed to continue immediately. The second time the file is written the latencies will be very high. This is due to the fact that the buffer cache is now completely full of dirty data that must be written before the buffer can be reused. The reason that this occurs when the file is bigger than the buffer cache is because the write to the first block on the rewrite case will not find the block in the buffer cache and will be forced to clean a buffer before using it. The cleaning will take time and will cause a longer latency for the write to complete. Another example is when the filesystem is mounted from a remote machine. The latency graphs can help to identify high latencies for files that are being accessed over the network. The following are a few latency graphs for file I/O over an NFS version 3 filesystem.     In the re-read latency graph one can clearly see the client side cache that is in NFS Version 3. The reread latencies are clearly not the latencies that one would get if the reads actually went to the NFS server and back. Run rules: If you wish to get accurate results for the entire range of performance for a platform you need to make sure that the maximum file size that will be tested is bigger than the buffer cache. If you don't know how big the buffer cache is, or if it is a dynamic buffer cache then just set the maximum file size to be greater than the total physical memory that is in the platform. In general you should be able to see three or four plateaus. File size fits in processor cache. File size fits in buffer cache File size is bigger than buffer cache. You may see another plateau if the platform has a primary and secondary processor caches. If you don't see at least 3 plateaus then you probably have the maximum file size set too small. Iozone will default to a maximum file size of 512 Mbytes. This is generally sufficient but for some very large systems you may need to use the g option to increase the maximum file size. See the file Run_rules document in the distribution for further information. Source code availability Iozone is available for free. One might consider using it before your company purchases its next platform. Additional notes on how to make the graphs Iozone sends Excel compatible output to standard out. This may be redirected to a file and then processed with Excel. The normal output for Iozone as well as the Excel portion are in the same output stream. So to get the graphs one needs to scroll down to the Excel portion of the file and graph the data in that section. There are several sets of graph data. "Writer report" is one example. When importing the file be sure to tell Excel to import with "delimited" and then click next, then click on the "space delimited" button. To graph the data just highlight the region containing the file size and record size and then click on the graph wizard. The type of graph used is "Surface". When the next dialog box pops up you need to select "Columns". After that the rest should be straight forward. Contributors: http://www.iozone.org Original Author: William D. Norcott. wnorcott@us.oracle.com Features & extensions: Don Capps capps@iozone.org Not measured I/O performance after caches are exceeded Buffer cache effect CPU cache effect Buffer cache effect Not measured I/O performance after caches are exceeded CPU cache effect Buffer cache effect CPU cache effect Not measured Anomaly #2 Anomaly #1 Not measured Buffer cache effect CPU cache effect  ZvQYnr!(!X"b"$$&&Z)f),,//7/11334444?9H9y::R=^===O>Q>>>-?/????? @@k@m@AABBACECDD-E/EiEkEEEEEAGCGDG`GHHFHHHHHhT` h65CJ h65 h66h6[a    8Ue<_^ & F(CZt<r'XYZvw^ & Fjt9:WXOPl$^lm!!V"W"$$&&X)Y)*c++,,.-/./=1113344444Z68=9>9:v:w:z:::;;P;;;<Y<<<=R====`^===>N>O>R>>>]?? @ @@j@k@n@@!AzAAAAAWBBB$`$^`^BBB@CACFCCDSDDDDD,E-E0EhEiElEEEE,FFF@GAGaG^`^aGGHHHEHFHIHHHHHHHHPIII\J]JbJJK{KK)L$$^$^^^`HHHHHII]JaJKK*L,L8LeReWenepeeedgggggnhphhh k k,kLkOkSklllll=m>mCmmmn nOnSnnn>oFoGoLpTpjh6Ujh6UmHnHu hT`hT`hT` hT`5\ h65\ h65h6Mr]]!^_^`^o^^ _D_E_H_g_h_m_____E`F`I`m`n`r``5a$^`^^$$^5aaaKbbbbccccdddejeeeeeZfcgdgggg'hmh$^$^^^`mhnhqhhhhejk k kNkOkSkllllll=m>mPmmmm$#^#gdT`^gdT`^^^mnn nNnOnSnnnnnn>oHoIoLpVp}q~qqqrrrsxx"x^$#^#TpUp~qqrrrwwxxx!x|s$GJo23DEYZghˋً̋ڋ&'(h* h65CJh65mHnHu h65h6mHnHu jJh6mHnHujh6Ujh6UmHnHujh6Uh6j|h6UA"x#xU{V{|{|Aers$%HIJo23DEYZghˋˋً̋ڋ&'()()h6(/ =!"#$% nT߅a]_zJԝ<_uPNG  IHDRo PLTEfff3fW3bKGDH IDATx흍(:]՝[  =3(F&i0LAƣɴGi&:2MudO:LʙNr 3"ҦKl8E=dqp֢{yҬ>&gz+d7a W#1+7ƅo)< V=:G4Wv f |9Z"/v!G\c+l'-Y首<ݪy,0W݂J!`=21l)s(%iQ\-ص{0g<oF<\.%b5=R0clqeb|ELse7dZGƣɴGi&:2Mud:cL22Dvs{"]fB3 Rx[%] <J2]lfN.x̰8G1$u|M#n1Oi0/ţLRΗc1$ edd(R#2*n1:_=ʣƴQpx*~!-szвy$c5yttU6~CEU4_ZyãK:gxkMs.!f/h]Gf]y us"m1GWY}9u)xCxk1MJ4uM5G[ux }u񎺔<-h auW1҅(SZxSy I5Z̾<4'ԟJ4hxbMÊc\'c?::GY6!%m#=iHţ&zy2aoV1,)qn[-f}c"ʥ8Cy \ǸcXg`<~x)\ǘ-q:ކǸD)q:!\sC}Bɥ8Uѷ.fGcXp2O yx Ly)b@V<}y̪Ql:q<$L\ǸG~1:Ec#3s}">I)1;wPyPE|Uj VgXȻzgHvy KD[_ǐVx< }@ 9Ǵ&xLϽЉ#%ȸɣxeC_GTxӉ<< sx,r.iUG-x p]ح}ϊtJ|CZΥHҸU<-h.X3_ǰLLjgqp95tli}J9<Peuu{R'\_G@z"?ջ!8ey ȏ8Gcyb!nr<.c<(X­xX _ǐxN3Gvޟ{?/m(fS .)qZ}ģU[qy K2-yyL+Ql'XUҌǥ#):GH'%\`)4WR(I<  *y*h< xr3Wtha5y<=AE3yܓʨXyt |dnp5V ,cXu4+uW ~`!b71$ѹ_]bOu=o+ѹ_]ժ`1h(Z?.cT.r<4]J4R5)Ry\GqT8I'H/"wfVi/x\ICy[=x K1y.SgNT,k y ?G9ǓIz'Í[sO~@,1$`͗9cvoOї`.~h'"4 hcRjWqS*-cX4 w:ǒ10ǴN񘩵OAe~!Vxfy~AոWӆXx}UgU~ׅy8G"\*~1PR }Ea۱8P>RHҼla]dxP(qufX/k2<"9i8ޞGc?[I/W z~?`}\ CR'Ȧk8QGy﮼ApL;0Wv&\ H?=̻ !H@mJ!^T:sb7[S:ci܈|:kg8["r1F74E$N]xt6gXodX#Mfd=?دf^:Ǭd߳z#k_BR+öQ@jpL<y gq&pL'e2"1NQ-FG%H'Ҹm|M<~zG'btK N <>1]JYㆢDs" ݪSy gM?1K{V<›֕FotUmz$!\U TzLqQˣ{(~u+&ӑG9ܜ9_1ll4?4$`0{ʙ{x<~JQn:4͡lI3vYPPAd3xlAGa!n1<=c9EZ+Ƥ@pO;Vx%DExLQ=D7IuC18Jeǯ6RD&+"!,$< a~}nUkģ{hCg)%#w$>dNyGdad;xvQg*z]obpc"<~i!G^}rcr[xmH> :zT;&f"Hj b͟3gKm]1ϣxYS.Pض/3H.PԪ1tG_++cރA)"NnX]Ԫ<5ǘ[+VVjq,أ)*xWȧ9s]Ǵ~W VNc}ՙr}>Bx'>FX6< "~TP#ڐ& <έy{I 5 q/ ɈAO-duS*O,?8S8[-J<:?{%jIfjgӟaՇ=I$."<Dž>/RpUEVU;p8fs{삑W+a/=)p P(j6+/72?rU _ fv5ߑG8ԴZw?s,Tpף*gŇEǩ<)PE2 .ţW\qxU6 n)`<.C[(XģO"hDıt\VMţ{1WP^G&;q49̒67LѴcɓHemW1}TL,ݪ.<> vbJ@c26VƉ<Īf{vf'oy@,ުj:=WcdʆC c}ߟi_@c9?,K:aFz11E9e\5٭( TC Y e~ qikxt]VUW?yl1CrbBIu`yLp$xhc,:GK!%Sǧ~xҳXq0Efe!Pr0G@ƣyQ18 B|G͙6 q 2?Hk1gvs;X~bnNwl 9jYA hmX0 |4˥OU IDAT>b ?:? jE9:zsGn ߗ;G:de{<?q&we*a.A cN~C5%)'qK(}aiC<{ȱxt<(} G PcA8vw5IL}Wi_E@|r}|i;Kz㽑D8_u9 [FpƐWǼp"Ս]/Rv`x|13:MȠ4닺]Rr4*|LdHLke W=&ߛ~1lƣPCRERu*Ax<(6LS)/"$bT 㘒Uf) x,O 2x.u:!s;x{V7o/)cwoBr; G?!Q@B%}M, c tKԏG˟zvڞ]Rǡ%y|ThqDglmm}y$R<~~N$dl;N*!%;#?!mOoHϣoT.Yu`{ 㰒N̯SmQ]Q Hcld qs"'#q;TFxXLـ#܏/xu\`E' |s 3q.lPܪǤ531I37>օԣˁI E X7E]TI!å4Gq4V]8 VˍGBD&M\<92js߅Gc1ɵ(#Q>66csX7˸]2x*~ 8AWGT<_Obk?wv$FSi'Z,xiD^{VUo#pDq hdrۘcM1`,pȿ3U؁GbTDW_udQ[<['lz5T$r?iC1Yud呎TN(+"R]zG+KPyx{"TIB&ڧ$y7$#cC4ua]='JˠէSɣ#2H'H}R(^pJw}~i'/S^yr+C%L 1i bpl #}JyLV=ygttnXrc]łsC[B 5_>mZ){;J:҉ڋ ]*c{n1H6#$m$):[ọ+Ta}S";7vZj8GG-T/aR1R.<[} 42H"4&@xhmfBOW#y S(>"ṢOi< &N,1 1D^*5xGІlA kc?䏝Vw;ɰb<q()m;^\٬1zJ=!>98;1 DŽ=C$-,0ssq45QSҶ <Τq,d(c.#bt(‡$y,TEo4P5֣<:qxHXj;JU ntL=9QI*z3Ǵݥ;AU|j6n#C70=wL:f;d[Dk~5 %;V1keX1bXR9"Ŀ.Iۂ·s1{(Ӷ=|c7RUg㱍z/@TNѧDcdc6MCoqe4/ʣՋ<>GIMsJ9鷞dy$yLK(u\(_:H_}NV#'Qfxrm!G}ܣAcmy<+) t1$>d^P; &W1R?>R !_ժQe-idx\A=xTl6 K>r(7 Υ}Ɠx,gxW{#zGqChsEWyYMyz4(_~I0l%n=S꼖S_\l=eJ({$LUEcl=tn>?؂㸥C |#iX]$,]&!$d f(Rz&v Kt C.`zh<ux4i"\Fx_P䱌n9HUW[-c#ytTT@0pq_=^ ?/ʣͳKK>GD;+ Oh#8 8 ߳c|15SUox\D*O 8*G5mg2nYd뀬JqL#$իqII6Wn eH&~5]GF&vQWvPC<&n'n͝j9Ci<\hN1-qí^!W^ߠs@n['IP+1^CpF*-1-ma\f@E1T<8I</Jqmiy 4 mnuCh+q 9t3ȅfu;S¹hH#P>#҇>WҖFY ͯ,>kS[xt;<§3#-wC5 Ϥ96&iQt,D󦥍Bj 6}CxYwBkxZ]xO($fPҦhuQB cG1U*!-2y6##|XmRd8G }Wjc/7Kcޙ:ލG4ט%MKz) x\y\ڜ~Ɠx@*s@]G*xP:<ՙGT:n%mX4Fi٤ l!ʢt3]~HƣKi$Phď&[ C1q]$֏߆l%m g$\8qz<~ʴi#rcryK~lxm} "Yͣss"48T4 })tTbIDAT(d|PKN1i̹K&T?)hqO3s~bD@tT RÈ DMYf\ CEeKQQgJ!͋ey htDpDC9JLpK>3dz"i80۱FZLnrq`44;5c32l=c<< H-vo`@NFTp ii $VaOi[ǛPwTT97fbG',YGKޥ.@%l^&JOB͉@ `EϙnG5q,v3ybM:5Mf(xEUCh9/1W e7&͓ݷ42+bZ{z>5{ļ1`MtrŶ^2K=y>nGxktMM"P(%R5*F~9 RK@zxn$>;E(U ⻍KT8wnK 茢.cT{ lIJ,F7|:H@U xb9}BCEU )}x|`H t}e3G &]YTBՅuB_`yԿq8:3[.'Coo%Vq -QK -<*& p*@zlrF"Ŝ^6*s?Ќ.yiBqTţ3;eQb%8+ 4ټ{%Hi{T.2ـ.zSn *Ìy\ = 8,"M ro!2$wLsxԀtي+: h<>a<1f"v]Oϐ=xSqA33j񵤡ͻO~͠J<\q.=P^.Y?$h۹Je pc}L#wJ-kl3h (Y>qi){2CŘbj HPg /Ȗ-ʀ+=.cBIb͉|k#`Kӱl|ːgr4_WQ&~©+"T)FAhzUETy_9nD렰hcr#t8:X8 12ZLna}.&CVX6Yuaa6cPG-T2Wy#nk-CdTÚ]-@GT [פ2/r?mE 9$*{ck1R@)*Fbup-o]wb4edvM8t܄4u; 8Tߑd'ʷT5ep&?zpQxͣ{CvEg2mIZ9t񉠴b]q)j(E#G5L AFХdr2U8V,!bU~E?i.ےK6tka%}B,(bŅGr$w1=6T]UiC0Ծ^Y7M7#hm=.*[2 36Rѐo@`*(d)NW}! d*ge<eƃ)18s\*GQt3&X8G\uy{扱!$ieɤqLa2m5eC9̊xR=>L)>e-.*RiU՗~afũT'ACbr>fPz(Ι tW=3Yʫ'Rd2'Ý3Ŭӻ4q>J ~|8~ژ?z|Ɇ_9+P#0YcG\)jdnN@paiCކK'Sr+P#ݰub$TN8iN Sj;CUa94=hS4SxNMFRF"8㲋]" r(1(7bx<,8Փ$6f߀g4Z V]%JfHzD@W_ΝH7d߮bW4TcCk8L:]Zh_Ǿ2 u$`ZRvn#{w7ݻ@v#x~}3֑xחݻ7ݻ︁F~ d6;n wq}ٽ3֑h2#dZGƣɴGi&:2MudjMc;zndWPѣ :j6ԯ᾽MWj=>:iVBz:$߾u^1j6!ׄ.n_KpQvo~չ.FCǮ~:W=*-vr?muEB]TqsҸsGWEI@y@y@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z HC=߹f\Q=”=k9|GXfA流z:!zl}z?VcG1#i| #i|^.#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$͡涽 7zGzLm;?xGrv#,x=?=qz H=7=6>/ם 99k=?y@y@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z|s{3#8㹼7z)zl_w#pxU=fImp1ϊol34 zl/z}\฾.J=wpaxNr4?i#i&zlmR0gxpGXiG==UGϣ@rG==FI@@q##i4;cG8^ H=z$ͽǫ*<=,Qp{z?**ftoS4z HUz^l}cG1#i| #i9I@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#iތn3_7z)kzdG@Y=NpcG1#i| #i|^.#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$͒= 7z+z^;?xG@Y{~z4{lozl}^ٯ;IsszV]#IrI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4z H=z$=FI@cG1#i4{loF7z{l/=”5ǫz4z H%=iX>+zl=34 zl/z\FG8w> \G1#i4z H=z$=FI@cG1#i4z .k1xhI*y@3TU1q#i~Oz$MnM2=b*㍵t1Gڊ8qVnޯY+zHI{LK749=Yz #9Gr7TcoɡP=Cz${CH=z #9Gr7\*.=ș{CH=Oh7%=G>=v=)=G>ߗ 8^NVa^O|vozC>ii0^aZ<ݙZ ҭt3ҽΦ1tm_\ =clޝx{mᾡAa^c2s0GŒkד*~Œkד*~Œw(|5+N->-#ԡGCPgY3 nGi<:ϽɪwrT lz#iG7f~~~UW/Y?oyy ҝ?|^W:^M?[??c?=>y;ž[Stz~Y^s='J]?tMfv_n=2{^}{S{ZÿdekyE?Gkն#1pf̫y&8OrZznK<9b35(7i65Tr70b}UrZz8޼߿Mk<ޤ0Ȯ?u [5z+g4O]MFI:y~jRLsX"hkW؝p]/Y^:뱳O'gx>4?hܭNju{4.kWF8()؆C03X_~pbù/kܤ7=bnC;n>f?Tc~9n<1G1u4f<"Lk4fo͎Xit)֘ !=\>|g~?b>wrs OR#n\?97F^~Nw1G#ԡGCP=Bz:u#ԡGCP=Bz:;\~Y7Fչ(XSZc|1')(&5}=>8ơ0}q#CaG>8ơ0}q#CaG>8ơ0}q#CaǺiN߾~fQw#ژźiïZ3=3V+z<cuvr>NVbVw8 l5}jw`6KYE_Gty4gc-XwzSf%}׏?|=z,zq#5Y~E2i]sz;uXkݏK)>~~؅g7,vŽq,[>r;Q7_a]wt~8zz*vy"}q;fzY:o;Ls!p(>ux;#n~XFOW>>kV3x\!Rú^arvŸy f(cv9}k^J4KϏqxnUh-7Su 7> qٽk˯͹t9s^e=^S|~xԔ8J|g>+M˒ܳ2a-8ơ0}q#CaG>8ơ0}q#CaG>8ơ0}q#CaG>8ơ0}q#CaG>8ơ0C}|/o#e*Wjy$W>##ۙ}^GG|@aRT /DaG>8ơ0}q#CaG>8ơ0}q#Caq`]G>8q=y<>&Gy}\M^y"}\M^y"}\M^ywc3j\j\j\j\j\j\j\j\8uspBח>>Do/#O4jJF &~N8=ݟD %s:gd^?~y}żc91X@>#ļN!PR.}},G Frb},G Frb},G Frb},G Frb},G I}#>Z.}},G Frb},G FrbznnN(qG8CrbRy|6bHqZ@>#<@91>/W@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91>Nn?.7'DwnG8CIqGHrb}f_}6bHg?o? {s|}G(rbR}yyrb},G Frb},G Frb},G Frb},G Frb},G Frb},G Frb},G Frb},G Frb},G FqFr/}32}\R },G &Wu>N׏ӆ?[_,))G FT^vqn yǯJwc[.}rYC>NS>BʁsV<׏pWG?)>~w8_:rDp},G ׏pG)G ;y}{rZ@>#zG91X@˕#c91~ߪ},G j91)G rb=rbVpN!c91w#zG91w#:_m>>]#WgoN?7gR}f7%?/E\qgkE %sOyCo|>B‘߷xڪ>BơWnF}z>~#}rb>r91^G91U91X@rbS@|pGX@srbS@>r91>/W@>#rb|~;rb{w8_-G F{:9_GNǣMG8jǓG}|j91X@L9vY}}WxZCa?},G &#c91>N>Nl |ܳ߷=9>L>~Z! uQsrb},G Frb},G Frb},G Frb},G Frb},G Frb},G Frb},G Frb},G Frb},G 鯛}},oȜ#$c91>~bGqgkE j91X@<@91>/W@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91>N#PeypF|U!Arb"}/#gkE %Oy@}y) ?<\91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91X@>#c91>~f7'ïލ->L>~P.uPkzy@c9lqޅ>#]c9lq?czyw>]If.6{o8c?rw;eM-W;7;=>|bѦ̇DX]^}p׃b*>^}4kxfȌy\gDOlޤ#2ͷwd>TVҟ>>wOzx/:i莇5ҏ<);JoSiWBfƺg_|)fGAfLQǙ-OM/^T:[drglW}es[cGch*8ldoij0QJ{<,cs>1c^cHvGoF!Ez}'""DQDd>Gq"("2NDEDƉ裈8}'""DQDd>|?Θ[DqZ[iOdZ<~Sm.:*YWr"Xcˡeyn?loy{L1?|}m }v?_᷈ȿï+}w">ߴy0>裈8}'""D 8ǟߵ r[8F^p#:oZc0r[΁WvED,T"0}q#CaC@[Sk?b7#kNN;yo,3st5Rtt'ߟ~wSXs"-c=-Ҝ~+E,}{ӚR-Ҟ~{w"}hv"ץ_9E:oMMB%/Sk>sm|qܾj딭 a:;^r\WU"ݑa:3yoǍUPS:3֞J)glԮ=ϥh~kzoF6B;Bj?n?>z:39FE}ܚv#_w؞ov X5GkPh7LP'~}V1ʍ[0Hw*f32VO+C6^wbZ>Ⱥށ3VCgdqy?slnC;̉=1}uof%ca{Js;:99E:kXWHHoF$9cHJjB㖥5w=_=Cv#?_}l َ{J5#ݫ*K$ 1Yx1y3tw%bkŋQخWwvD"WȟowϽ{ߝ3gmC_ٺ!z+W7nw 5r`Ɛ?'Mcjw-DrO|?=!H?G>8ơ0}q#CaG>8ơ0}q#Ca.k{G5bS7y]Jit}X+-^߱>Ķxy>^._>~?'6`~A/}}t:嵎G86vx}6x+{Wt:ơ0}q#CaG>8ơ0}q#CaG>8ơ0}q#CaG>8p}3+IENDB`n/qlj)RPNG  IHDRo PLTETbKGDHGIDATx흍z۸y~gm!chۍGH%[nSBtG@|tG@|tG@|tG@|tG@|tG@|nlz?jm(/].vʢ.7Zoa${/Gc+8mW|?|ܼsqEss[ׁaɳ0|\{xBvaljأ]nUwF`$by.в!tqiz@Qp{3|TWxoOkPFT耏:XBiSXqw|,(Nc<>g|wi @|tG@|tG@|tG@|tG@|tG@|tG@|tG@|tG@|tG@|tGТz Xb#8GztG|">©8eǮ<>UЂ#>>|pzL#>>#耏:#>>#耏:#>>#耏:#>>#耏:#>e?Ga|:#>RȾ1|G)qB>|q'D]|ǃ$w]huG|!;8qV ztyޮoqn|>!;8}%Q y X_j>J2 aP?>Y'j;>N3|Uq>vBӐw|>!;8|TCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d'j;>NՐw|/ >Ns:}8#>T T xL =LCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d'j;>NՐw|>!;8|TCvqQ y G5d' cyJd|ԫ%*Uqb>>G*85Q >N@Rd"<8-}G|R' 棏D ExqB>Q >NՐw|Qv ۋ]1v ۋλv ۋ8v ۋ/M78v ۋessȮa{2Udװ^|ܽS7[Ev ;EǪ(QEv ;E=UW>bcljDϐgDhQv ۋ{AQv ۋl8v ۋNOZ>_?D5@1wcdLk8S/c*p^|5CLk8S/~N*p^I=&L߳J4#w_Ùz[=t_@K?J5~1CLk8S/p#CLk8S/p#CLk8S/p*"nK?xmL7寧U?:HO/,<7|J)kd8y/p*"nK?]ߊ#nK?=ߊ׏+K?]:>y"nK?>wLk8S>smLFzwN">p*"d{Qykd8E5宭)@յU2Ekd8E5xҌ8E5~K3@ՈVfāl/׏x^T#xmLFx?*"d{QU2Ekd8E52o1aāl/ߏW3F>*@Ȉ偏w8E52*>+@Wѣc.w#\F>>}D9'/p|Sāl/a!G"Dt"HNщ#":|$BD'DD>!G"Dt"HNщ#":|$BD'DD>!G"Dt"HNщ#":|$BD'DD||: >!2RG"DW#HNdǯHi+|>!z":>@N!G"Dt"HNщ#":|$BD'DD>!G"Dt"HNщ#":|$BD'DD>!G"Dt"HNщ#":|$BD'DD>!G"Dt"HNщ#":|$BD'DD>!G"Dt"HNщ#":|$BD'DDghޣ:Dt1cuDLb=>FUaΊcTLL#˘x<>~}ܕ~N1bDzwYK)|<+2p񋌟]*|<+墪dY>fZ*LǻGHA=S"& x|qItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #>~=ew"UL|O >TqD2 #>>&UL||*HAvDqItG$ ;"y},S"&UL=>c|G$ ;"8Ex$#i4ddG}w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*HAvDqItG$ ;"8Ex$#i|"w1ddGǻDWqD2 #]GL8".#&ULx*>;"Q|$BD'DDk#r{*UEUFwxg#vgk;麧RXQetǮ1|>6eQavtUGe_#^w+2s.uޱ?쉬"?닔Mڿ8Z3gY+ûˏY*h~O5bޥo|Fd 4FJ tqw?x"7SPn^(?e Ɖ9f{!"Y4" >耏:#>pѪVyYvc~f}<Ӿ_wK}sU{wacU֧}گEjvߘ7NڧLMZׯ`Fhgi׏3~{oFWV}~۷6sK_U/ϻ_ѷןݯi@ s|l<<5O]]ۘ~m'H6vszL!ږcxVr)>Ϻ5\}=7_8^vX4b,3UUx-b옹͍9cȼslZ}l ɿ'RݖW1M\#hhWWեa/֎YoXSs\O=m}ޱƪ^#hmբ>v/Aڍ|/VVk.PĘ/dn;P?+nlblm̻`Yӌh~ZxEo4Q6oޘkUwV1c[c;gӜHq s|#=͈I8LuQ^s,dc"=M~O "|5O[jшX4"gة պ3I竞iF}ӎ55 wyUžDb_iO5>3rcv4֕=>2hG1Vyޛ9k3_ Uw̾Ӻsڂ~nzkE)鸣qOI:w4.߷舜xL|?=v}tG@|tG@|tG@|tGCyg="LGâ~疣(*Ӣu`ǟ _xv̾{;c HvxWVB0IQQ#>Q=s Ԏ#c Fd{ՏqPoQWt5@|tG@|tG@|tG@|tG@|tG@|tG\.ę_LIENDB`n.h( S^PNG  IHDRo PLTETbKGDHIDATx흍zD&zgDA@ڥ9߮m15~о{>耏:#>耏:#>耏:#>耏:#>耏:#>耏:#v{\MY ]hg+6b8~z8}}<9@G؆a1u=.Rǫ l0{>>bkܧ@zE7x^G?ZDS.MCaGjk/W;zW>vu]5H[4晻a"l0{y޾=~=?<ܶn;.WY%l|\7Le|U 0ry:s/4Zkhq[Nyn~~ńFyA6af}HmDǭf؝g s |& .qn_q؄af>>N#{sm9pǍ@m6EJT 0  ͽ׌kON@\]0wzMfs}[(׹fdKF;͵ݑ^,ۏy9` М* .6fyfmhM%y2@|tG@|tG@|tG@|tG@|tG@|tG@|tG@|tG@|t8{ƿNGvz-8>pƬvGw:06>ym.ߟ5\  #Ub>J >耏:#>耏:#>耏:#>耏:#>耏aڏk o#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >Bܿ-qG'>B}l/5~щFz YiD|q.s~| @zwic|4wt׫!ݯR5iy0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a \k!*>#$a҈#>#{~l0! | wGHGH˅GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | >GH#a0ic|41 >B! | Fo˵~щuzwt#^G|D>nVqG'>BqWO21i cppm>\'+>dx/_ G0|^. >B! | >GH#anۧy6uF>_U; *ہ}Q|v'Œy|&qJ%Lㄏm#>ǎ׫z4;Ns5;x *ہ||};xbI<>|ǃ*n&>v<珃}dϼ>89rWw;sn뵕}13?򵏿>d=xz['qhǖ1|< >Xrn%CcU?޿1`x2@ ^954>?|x`ɩ#>^,9u7|ǭf\n61`x2@?j__q]>t87`]vEm6x#I'.91ɋ}1q_qnW|\\\Wx#x |,u>>|ɀӡ'>|ɀaqgR2r|z@;98١'#wlǝIwH:?Г̿ouG||9d@||#W65|Tp=nd㝥ţ}^X3>_ν^|q}o |\8(/I17Cc{G|;~>x؁a9ɯqF}d|\?-犏17CcG+?\?G|;μߗ^ q>fh| 17CcGG|Scnǎ ;ڭ-f8:Fw}of6藏ԟZ֕|9OuϏwϏ"I>?>[^=^`]WLjd%dFdAGs{{qj5?o}_>SrsW|cmcwܜ5o7|7|G||쎿?>#>G;~?q0|L(cyd|G|\}_>#> CᑼN㽰s6y|;u;bؿ)9'ӝ/Y?ԍo6ꎋ<[wwfˁ4= ]nLlc>zuc>1KGĘ/}|Udp(lZvݿ2|<%wי8ܿox=gw<nQ |:'?c |:xă>I|+9<8{hǽ"x̃>I|+9<8{hǽ"owCY>wCa>/G|j:uL_]Y筭2GV{"Zqqe"Q5Exy%=:>"Q5E^%6EZE)r#>jNg}|::Qңs~)US2Q6EJ(9:Qңgö^ %G'Jz ?gtG8?N(eS3Hm6Q(78?D)2Q6E/'eS3>D)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6E~DIU|(ΏzW'Jr<~N(eS3>D)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6ED)2Q6E4oqm`03ؙO'`{}ۨxr 0 }?k뼜mtA}_27d`2oOlk<?\<%>4z`o6$CxeBhmtNNhImg`v6m2ǺFv%}h3FKm~veŝ:ZŁ8Byٿ_<2ޡ6оc0NcŁ8| ^2mPHmw~yhh>p|jgG1@N/mMˇBh/vyPhmhǝŒ]8Z8]>>J6 zOV5@h83nwg6Yg=6ڀ>h}mɕHvhrjIgMNkϿ?p~IRïE;awd]Y29qtKKHYr~uK\Y;KƏ/gҿ_Ӗ[W(hWP>#|̽io/I6{m'v]]d E+KZrNܒ6edgǗ%i_]J[}OY29=]b%mzR.-EۭL,}PtG@|tG@|tG@|tGCz?7`6ݰK>/&vFXMzuG=%˗_+㯆_~]X~cq_}lΏ<:!e v6>j\=/Tet6\_nQv~c#׫igkc?\}>耏:#>耏:#>耏:#>耏:#>耏:#>耏:#݂"oIENDB`|Dda5$xxN  C *Aimage002b{ WFPx*{D'n{ WFPx*PNG  IHDRo `PLTEfff3fNbKGDH cmPPJCmp0712HszIDATx^ q;q2ı:Zk;:׷B68?;xg.<50G9#0y|\3#0yk`sF`g2G`89s1dq9sb\s3<9ǹg.<50G9#0y|\3#0yk`sF`g2G`89s1dq9sbk'r6}nyF`xЂ3k6q!CysF`xθ^ F&M!BysF`xθNcxŜN}bp1%"TB3jԨIW\<Ll|cnOҺ$r+;r_=NGR"!@o"Luy<ֶ:͆BCnJ$wqcyTOS3y|ޜM7'W񪑎g<~mFy&oy_ft^ϛG`ٛ<~mFy&oy_ft^ϛG`ٛ<~mFy&oy_ft^ϛG`ٛ<~mFy&oy_ft^ϛG`ٛ<~mFy&ϡ~L?o~9q$w3gsǭsA<ͭ+<O3S!e}c|5EiKZN(!n*6'x+&W#Ԍ}cVʓϰ9ydUuzJdNN6_/8"OWXL6_oQT/Ts+]gI ^d1rz3?F_ ͭZS7 t_Uh$ thOh}"MGx\_?g}6ŽgګZC'34?ګD6POY3y\h\x\/"G8-lY8hY>mUߚ97^$(\a<"(ӅQ۫&&/KyLQVC&Y2Nۉ(H&Ic"UR#%^{U/dJ zid uyHWԴȥ()%GD#p" ?k +Fqcq|Y^DhiI[ԍG\E6UN&5~#15Sx," Ă&GӶ"*{4s t#Fyh$I4qڷ&JMd%O164 G #Y )6!Y'=y ׆OmNMDi`}{O*4$y$0j :gUD¡ӺMIw3bcVcIh8?,!N} }L#_FjD6 yZ1a͜b.Bl`0axCsi*[?<Z< Ǿzj7ZzQFo NGd0Ts'0xcD@Q&)pZ Je;.Ε2bA)ǐ7z !0N@4d.pyKc5 ޙĊF.5[r^} [5VGXM ʟAWjnD?ՋgxhN{]Fy ly U RC<`wٽ``M99N}ܮkGgyB h ҍB\6)H:Gpo h=!ZvGb? O>u{?)X%hTHA=Q&EW\-J1b@Aw(iַH 飕ɗSXTBF|2R4`zmw(ׂ84hxj҈m)ku1GWaCy̧ $kQw m%ܮ<&1`C,ӈy=ƣbUIM6q1KգxUq3o>nu(cciGxGXoZCQҲd_*ƱbƩџ 8x"tPQ/(bdกG%{BKvQqs-6,M}an&2Zȣs,[6ߦ$*qLmoy܊q318YmXB:vE:(Hrķd 0P[QN}dVj17[[6 $m%bO7aq|@DlÈ,<.L֟{3J|2(0`-*M7`yy>L'#+I4N Ш);uutRU<ڴb gT~.d͜!LSv?7x]x+@Tʲ>e@F3 =͜}?c'QX-['l7OO5s&r)G blv8Ԟ#NX8*ɤ Za_%`QE=t 3O3JhOgcΠ( gX$<I4<=͜</G':^|$ɓf ˟NGɌGFwx~G9NJ@4lQ򩼟粞dnj"~wD%l蚸9腐m׊Ǐe~% Vn,I=!hI+js4 ߪyz s/Ԇe@nn籇1<_a4a|](?X;(툯IG74EeaW?}_E](9r<@ڟ2wA;&ne)HN?b\tddjGqeJ'1W}7eY 4T*`؏(ϙDzN *=[К<"Oܹ?ţI篲>SRdSq*@VؿKesLSoZhJs3HтéA+tի+gȪB!q-xs.=>*VEkjD?%!ۢQq-Gxz]gd}ܰ"ƕSlB(.t0I ƌSo&ڱ #O<%/J@" 8fe=jc[Ug4$&uVqyt8nc[LzyH^<"du}L֪FAUD)RuU\oC@KoN}lEp}t.\J`OE2`f+U$2#~i^_5-XfBT)lYZ ȓ{9Gg2O=[-"0J]֍iٿpgTaȾ![# %؝nTIڂy53aY I<6_.#b=8=J' cXpY#GהtxqU™Dg,cH G+tɉk҈J;Hg(eF9yLuϪ#Oq9n8k)vC IœH*YZ5]\9utUyU <"wcRS#( )䞲 3%@Pocf+!9y<>ߐ Jãd4+fD+QC"<0r;!~<^c;Imq]zQfk"݌[ ٠~L=nJ\cYb. $z~M0j]Tc[Nz),tU"T]!y"I6l&?Nb^ㅡNpKx .\>~XQ XVȠɣay@vO%[kc% Nӻ~'ڵ Hn Rž}QPΚ1}dT=[uMOjhyϛ.OIl⻼c!{Q2=*H| Vud'{6ۿ[OWY},(#M$dB+(3W)Fim Pp ZC{;9S tx>BUx՚YŔ1,k2?ƌ1@"^KɌƂ?AncJFRiB}7< ō<$|[^א`T sE;A(H9 ؁񜱧ZG8uy͑e횫%ÕTLly"?qwJPXo^ܡM,_ze;؍ZT #ōg$ z! S t-xH7\Is1EHԸ ٟp.=rOQnzE\}1>6U#ԽmjgP؉ŸaJ l6PQ޷j@P‘WIG*-)0&"3.lqڦ&QaSXem磐 <ǀ9M籨G[P;p∊\= <շ (ϓG$UFOxN,P'3ۡ_u 5zr ՚6.̉瀰1^.3ДTb8"6l*0OH6c`Gg 8Qb#/gMm"@GGOH@BS4u6HQL }Tq= ߴG1bO Hd0cuE>P<pHvXl15G^y??+H #}K3Y]GE}5U)hJNkO!{\JUG@|̐Ϸ (mݝeƳ<<./uB:@d0SC,Bݴ,?t>ycf0XjTWWXS)Vcǝ(BeKWaVHURE7W-Qg07!1yT L{uE+I%X-*U]U&q Yu`Г/@^},nۥwEg$s58J 9G!փ^ǍD0cy/>TyK,k<5R6j20LGˬzj1>z|ULeuȅ(q1= =lDVWUӗN7NQr]_hrղc' ";0$p,'gq|2dWdUm xd c^q Se"C=\ρ}&P Xql%E6}Y D^yTyIJ: ]!cEA{ؑlO-H-I˼&hTy3)1jvЋTB},ҟeCZr~kdžآ@܋:U{zWx<7ͽr'j цUL~ ajI=ChFPC2(JqydPq>:*,V8wxϲFj<4)L0F1c*f;PN:ay; SSi;Ϳsdz74#\N'yqv<& cZ8g*bԬU%+KPmq1c61!ƴֆJmtP__0,s!\ QJ,iڣ 5' ,9!` bAcYg.#1cY _n;Ji@xlH5N}e;Rd*!êxQ*Z:ƣjizp#< -,OW)p۫0Se'3Pyjb M= 7ϡ s5^#5J2<+$g̩nIb@ùb~`MaLG BUJ{xsEWՇ79=B׫C&?B%RT93#`Wf<X}A}$my>F׶Wb`U#´O O#^]G%,dB\J-.=G3Ю0P̀Ty-\Nq, suf G PW0CqT;(,&XRGVҺWwS:V+'<;cт7PJTA[ v+MCFjtи>#Snb(.oq= S)_[~<;LMMۑ (潛Wס),F%f?}XvXn@.XxN($Ugڭ|uy4b^V~~qOqMdU񜑌U/&elت\Vk(%yP<[-UGT*N#QO wX %_ D?hԫ8V#hŪ+ѦȦ~#_jc N/%10WxL+HWm6J?+7B?j:N8`kJ| R(}c~zVl{>e/( LsDxZ:DkHh($ɴ483#yK-tvwQQG].Y AlR6-\++ٱ^ s8y}38#5a KΈ "Hl={;Fcb\E{jv3ߒt,Wtu#[ 7wq'YQ ̌F.U Y?ާ/n(Wg,R+KP$=*(nkn89&K? @I$XN}\ȣ[>>UU+}\{'ПCڢgq8i6 )2(Z#a8My^]ide@nɣ};<;x܈\*㽆-#x}ڜKi]cM@-P<kSTػx "=rP|ǫxXm=}T?6cWWT d\c,/g/ X-f2*Rkl7%jY1=Qnzb( a vA\_c)cWثy.¦Ȍ)1YDJw}0J찗Ǽ]Uqg%[";5?A9Q"M|Ȱ|:Z0{x̦Ͽ5Ujkw]zxTmT`y8ڕf}VUNjq3 uI%k)Sf5w١p"(=)}LN{y8ҽ屳 H$ ) feN;$n^^tAc; q#ߑ+yL*iC7h4?kgFϡ9$?WZ4yvXX]<)hUcx{CUkVk7ZY o5;Vܐ{EXdҊcT6(u_k]YҀS@~C7->b &Ky+BJI4GzN$m`f ^DҫpLC<"#󸸍},X'lĥtǵl@}L$mcǔ@ׁL>.i W٫qaS]ql\K['!pH87C %+)DO[4c`Ԇq{M%KGU}rĢ60M9G9qy|MH7Q|mٓTnlY?q:nT_ɣ/Y5*f %r2JC97"Lwm&IeLa,Gɣ#\^Xf?T f7P!V1VqtЊZGNd]z!>sdwy;Ri1QC>kXq/T^ YBj+G5Y<1wuW͘6y,OVwJ@~}b2. bZB|Sw`*?ƶ,AUexNGsX  LJb)Ym2GP!ݜ|8Y9[<౮_E2<2Eܞ#WaL1[;c Xx\ WEDѪI݁ LSHa.Hv0Y l8lYBNe?){|Gh=_ @{ht@Bf|;9i#?CR~e%Jt] ˯3Q@$kw:+F*c* +q>Vi&N7dXևdV,…}(QsUGY;,mnkwA<-/7Mk?NRzf@|Ȍ58Rg(oy=lЪU5<زWSg89j0*8N:rH0GֵPrnG\Bſ!:*Ђ ?pJy ]I1\+S\!#`G URkuexG\,c`7ƐfїIM##z4VAS eSQdyE0y\RJhu01`wqyDvvBU!Sw5Str (DpPO{{@74sౠhأ8>Zŵdꐭ4x J. D PNX $9>0)uBiq\s4a;|[Z]VRBI`Hd}[@(Su5 E٨ E%&+LKVG@'5ꃋĬ\9ئ g{~AzI?yGm|)@yV}tc0 (Ȣљ>ra>0l$JSm)VC)aԋ"ݨPy\ ZCG΃$#F=1;p9R٫ FVeҭ<Ҿq71c;/VQ+\,rژl哂)ǁL>c9JX}Vr{ @;$c.'C-Cc>hb$h Lc;s q+ɵAX2Qy([}Xq#l"r9J"mXZJyw`ߓy #G nUd`ĨÖ^ħ(&8|u| 0)#oǑ7¥gD=4y%H@p`#-nêa0cq1iencjeydWMcR;xsYAs &MB=>Q[ `k)jV8WoqX"3y$6|RK'6+QګHAooZ3bz79AcQ0S-חvП1ۯޣ")>Zw2P̉W>fi4A <&I㿬S(#b<i>&>\3ʫy,Ï# חؠ:KΣF(y\R4fJTG)q ]a^ށh',xTaZrP=p<}T^?Yvjو /h\#׈To=/E8fQs1L#<SN[8X%'W7f< ޣQH<'IxBH2lf@8G,0 U^HY?^M}ac<.{)P4_@s].eVR&GxojC U/@C|586#UXh eO2J (7W3Ѽo5^PѳA7Xk%'<:֙;SP8ʿ.HD0hJY,=h[? !yT|+.;#yUЙxdG!n4y#|Mo]=̑wҋXEҨ?!$m~%3 uA#Wkou ne1s'Fzw-VKls6y{[W:ukKxҜŭi_}$UEoi49٠DMToǁ<O1 ^*Pw)B^GIgȊ7,f5MQ r?vi#U-KܨU%U);ps> ]?'`ǦBOPuef$Qb>GrˠdGNGͺ8ݐ0qHT5 '؃׫g @q.IꨃH;+pfl UOJY%[ȒrD9)s}{z^ui}!:^͖h#">+v?n!J V7HR1cyH \zɣkϱ"ǣ <6 kV?W3o}r0 嗘K7e79}Xc> (q:xipq:X3nf}MxN}<:qHV#P?`#)Ym<nݠ7Էѐj:Q ܫgsW}@~6s<zȦKִH6hc<ks8^Ys}.Ep+g{YԽ9[F}V'k u[,j(_1|;v\17!{U X_vT ֫y, `# J}, >GYU}^P:E?"/y9ZcۯPT1Jz`~khGDcTooC߽qղnM-1"sG{#!̵܊Yud#E[ጯ_Jp|_McW\Gث Ԋ[e@Ԣ7!{U.Rqfz8Zu_ ^w( [$nSgC#y[ilDQE:''~Q*v?t7=xḙj% hIT.ģqbG֤ VDֳ( tq: ŒGٚnm]NZ<דBoP76#ZIFP d5`u$;N{ty0Ylvc3fx1G U$f>n}QTF{%#>Q(S_tAɛhmQ ~r{USml 7"OWyy\O9\:V6QrNI:P˯qS£SK1^DZY6$UOd7Yj:R%8HV1Z4^'OV]&քGN}AtSײ Q?5]gT rTVJAC=rC|4!~a<ד nq. F#(<㑇TZߋ$e6dH/)7vt17y>&I\Xy#t7Ǩ,x\a53&.A}DlnGR вJN}tSTO[. ^ti`Ha]}l^04}L>O<1Փ&1xP'9I(/hWU^!UyLIHr}%% 6} XTkT/V9:"PU:??d 7-c7:i{gګ%={x)yX9n蟕p+DVDyUjs{@%zܤz<'"#Zݞ>~G xofW'me/&*8"xQjܩ#£7f#@uܪuf^qG܄&_eB<͈ʣ.VYS9y`34D7w߬v|-p_n鮆qԿţ5{NcK nlF2X׎",~<sBc@]q>F'_ 7 `hL Hqyd(Jj]JQAe%~lN lˍ<<jYC 0[1T9#FkTn*zj(ɶg;oWcx ,#yJ%jm6)DRj!UNݯ4WWŻ˕hV^#E:%L+(X?K֦@ge H;uH}T>`PN#1Yɏ"%P?HG'8z|s?PB֊1PkG[B$H,h5-.o U{TJ+P 7L>ט<_m +b o6W+q8s>Jʟ40J%P*[SG <'go6MAqGx^c1j7}(*a2_MI:{6{GXQl.k=0ʽZU~]e^@՘~n&D['eá:Y$P b1.Tr"\ B9q BC'6G?iyM)BwY`)$kqT{αkcEGr.G:viٽ]ha}#L` tCa#2kuҒ'dq{sKJO=&;QLG9*٩>Z5Y6HULs3G^d [rAyD @9r2ɀϙ:~!`=BPTMh釣VΛv 3OK#Co|SJ7 y#51-5PCY$MͲM,ʗiC\)l. _F6y|1un7t-8n'9~04Ps6{lQH4 'bMޙ| 3c!ٳ 3aѨV ŤƦϹ|bm+Rzy kƍs(Wa5X,O*{^MokH X̏5rUޑ7F.vE3 ߤ]̺1I7NjxN l,D9P?TH Yo;VyApWA}+erm;s}l^56:W{`xM _$SsDQ+@oѡnPN!obsۺꤕbMڡy!H*Jg3ڍ0>fI}΅>ٛĺg$Ƞ)u魡bi~:6QtHcr..Lg7[wUZ·CɓGzGɟv.9-#ꧩPseg\w:ǖfW^[w٠Ė©\x7Ƽ)7>~P6iIRPՠ0Po-d[#怱~t(1v|H'9٢F2~zw[+e(%WKX}2s]ҕְ{i%3I]GůU3 0#֒vZ_Lr?{@>^ YUsj kZ8Lf3*d؀g~ w,n0%4y5'mY\?honNIP Yځ)/Sp}Ȁm|7U}_na}L#|:jb,LKH6ݫiV#к,mgY'mM-j⦆!\j<&z ZqXeĀk͵mWZDC/\ulMX LaM41vǾBG@.MpIS4vGE\RS oD/.Qf<|D>op bw=mϯiOM`1F07>9d5Ǭ5}gdlH >F<2Y"p^ Zn7Fh0#.esޕ=΀]w겲"AyqL;Htb _\]Q| #Mwy_\:?NS&P$FS^e`sv`HLXĄON@=Ȅ^ɠgrU.ȸQNqh\iC&KY0ܥ},1 ~*q(zu1Z9vR]2֒"&/W]lY츦z]kع=29c?%ŁJڵv!t9;e_c9xdvfq vn :nC:gĭ3;:#K՝cvWC< mA|Xx :hS5籷y۹&n5y $ zz1P?1QFG7tE;tlCsu%0mf[)8E}vo|S #+LOȺu ՌSzh16G_EǗU1_ڗm!A {EDЮDyZ+o#xkkګ5]1/1;5s&mZJ"ޝl;7bb8`?B37P &eDkLO2+w#vxAĄռ8(YԳ<_1blSp\%%F ]rꩥ'yzO(^l' ф.]ݒGc9͆*Hj1󂞮 fyڌU-6qxtfvGZ5NԳ-t-M8ϳ3f2+~5y\Nx⯍Klpm婍Yr coضG`;1U$xgFyVP1sA<98`>Gxr@Gu8.Kxv{/\wFL 1y:6l*Q1(AXr<؝ЯY_a pî[wx̧3խc[c#jM8ghz؋x@sQq{ OC IW ?tf6 z!xdSAe-Qh)ceKB4&Ec<:̒--]אo8Pҵ+yhYy >\W'g; 1%ֻx{4^HMq[L׷b2B,XǩCF72uEB% Cl Ή;i߲g}6x̚nAPhYښN`GC oY]Wnp=ݾ`KIG-]%ҵ7nR¥ڒjIxܱ&lԳmK,bGhm뽓Ɖ&:>:bwO˶zk|U87ocjB:B 0:pq ]_0e_c]R&lHB }MpGL)7]/Yq(ګۖ@a }I`0yuMGб-T%>u[s&.{8#0f4mtN!co2[:_PeGmlzG U}(O™[{)Gw4#gC؊1r';NBE`'QWڋF;3m^1'ZA{J>7pG>6qnnF x>0E"N7o>y%=Ai F>KbO\=#)@RҭN;Oh;.ȳAG܃$5mAyky523x#tQsĈ].U+RD.ߦҶy#SV䮪@.Ƚ2i*fѤnB 6TüLcMQϑnxxS{yD/ɘ4:'u@t1SCSl/Ḇq+gϵ @uY5֥IU翡}c`#Q19jNg3=ɀ+T C{?1<'D~(! ԇ -X9.s`gyGr Lً ^"$҆+rR0'xPmcXBns r?tuNE%Ͳy掱Hꄱ񶊬 s_c^:N.9R;&6:x@l&j}N3+]sUTq 3aP15>r\F'%ts4I7s>ۄ`BFgtǽX/(.|4\&-GWݳ83yLcǟu;vKzv9nF\ڎ]߬>jq9Mol53z|,WOt& +o Kc}.x_\'he&6r6-j7 YjUp^ x(Vx%W/lv{B8t{&~!(sTt(΍_Xm9y,0>8^cqAIc ~'s${?wax (l88*IGMY';; ̠԰W/-Ex,+<l{x3>cCUڙj7x̛9yܽfF`ǡE+hCt4R{x{Enwt&i;;qp\J{M8`MRNj<Gw߈/9y1t"'8G/c#0y|Kd 9zh8%[.~NMi;vl92sN10"'5oM98k:9'7Y z|k'E3x#&/qC\9o: l#w<9%a \8{&OmwObVF`a^K!vx l=~r 9pila;G`039{4yz<WN{)qx88`l>x˴M2S{s>߱gwxhv|mC?vxs㙣;#06DZ93Gw=G`l&c5[8s&g{Lk#pL/֝X<1Z9-x|N_;Y-x\c`sZ`XwZ`j9}dqisbjź5V <u'k xN ,NV ,X-X<>/֝X<1Z9-x|N_;Y-x\c`sZ`XwZ`j9}dqisbjźǓL;m{Z's[}EYIBg =ݹ-xt(V 2EMPؽRmI]x/֝X<^1+.X<~?3oq~Oa%q1Z\~ɿ靘EW,.Ooopxb/ILĵ^E?eǞ jxJ1toR|qyJgC)pG_u[`8k$c%}}W$ p@QIG0c@W1sB˕wZ<m:blnZk0,첋Ǿ coo}ZXx,24YhE ln.#hٱdκ_#"CXR^c Ky\[ K"ϳO??n@:gK Qݎ Xg0ﷂn12c/Q#&=CcH.}qN0,j^>/摯a\#"]N?R;iK؝oQ2NCibG4f3J+X<bE䱐hsEERN>c=ktF}?#ēx,)3sD s2c#8.s=8n;+pb$',"B؜#1coG"ދР/t9?[LqsMKᑪ%Ą`G,^zs78xGπ$Eq,^Si'Gmgb D+gHNG>,.O7r^nb' `kJ&>d<5br2L!Bn(±=l}LZ`El{O<(%}i^ʗ\ay=~ 'kg} SJ"cy,yf\Km1.m^xGi15d1./1==Gi=s8p,n@9B\\\^cR.- cy ~H6vcX.tV?o CDtle_~A=Y`C:N8"]K#\{MtGxLِJA19Ԃ&@ƃނ(Lf_wHgOXiDEy[>ی}#4Jk_;^|Gq򘇠&)p#ϲq*Y<ܹ*<;y0=?u$E6xTRD{B'( )ll/@nS3yjfnS䂰fw㸉8g&Vϴ$_G;_.~H@ݺ @`I[<^ޯ9anOdmuYtv +<^%_#9y֩W؝D`S.*Ǔ!-sr<ƣ WXd=ߊԑcKOFO8u?NXa6n j_Y+#-}+qTu3<|/cC#M$9 wzx:⫌V_/d>'P7\WnmKwgx}E9̈& okM+Dg;A-8!H-,J8q8G'|zGZ?kGG#6Yh(Y Vǫ `O#8>=c QdI}]i9ça ^ⱁk;Eǻ4~F&!X~1DOMNǷEO]s- \g۫q &E ӳJ<ڟZs5̱[S9|hWLI. 'Bl xN4 kkw#Vˤc\`)sdzɓ;c<keT^?1:lR_rG"4s|yipT2A`5[ỹN#W񈅚|5eK> X~dX+*Ih1@eחj]#"J̻J|9j l$to<Gl+?G%9\"f8;ǩ!o1#v(YbԆg^c ~]cd\i3ؔG0b h!lN+_M(BUol=GjxyHF`_[@<'41,MˏW<zy<^U)yAL2`HK?`{?i^mW(8ՎA|@j j>.2Qrev)%޾&lp(~Ujnjbč°M#5_kܢN2V\&lv4ؙl1TQg"}䑸>\Rgx{/CظO32U@Pxb ` sqh,*!xVUGwW3`* o/ZI0af)RK\Q Dc@&c=݇bsyl/}c:֦v ez?۪[>lpU_B44'~3;zvG1R 3J”; -晏h[+egK4\G<Qk%sʆ}1h #(ɷ!o[j <=*H$\,!al!r,\eHW)R!{Ȼzr8峪XPtGtLq,o2IM{T ۅ G 0=Z#Dc~f*?{@>5.\i\$&7*15#QϽ7C@K4uyDZy.u} ydԡN#!H_uFTR!bgxg⚄k&cU,>F)"9`9zdǎǐ{X1@cn?q >?cUxn6%Ŧ`=Glͨ}luCЪ;xZܧ, MMtaZu/쬒 G Y7W,l=:eޘ6.E{!)!2;5ݘ}ci: EzDI(|>"_aDX 1# VvY.?°>N*<|FoqQ4ؕ"M=ˣxgcf[&DGmr?$ڀE{Lcfm3X3*ȩYG,c< {W;x>Թ7۫7=cREU1BCc$q}ܶhYgj4߅t%ءqxg3&x -ØFyxY}}~+ׂ %iH%+ӯ5c\$ObBt/c[||tkT4p, Ye*"11mr*r Ļ*YIސ١$QxuP [!Y4GuRqw ~d)S:7L(Ad 7qG%\0#ưCx֊O8WSn9A*qǪ.K$͚?>Ë~x1U yT,3lK\ g J;?AF(tzT=x ss~4=c>~>`DOدN|54>`,;}cf\?^F[ă/ߥPR.ai[եf#y0IQ&XjXu׊sYEE }|RB/1`c R3|ds ;\Lq2Hxn< (]Ďʨf<^cVQ10|B,ʣljY;Ĉ|)4v8ZbAvh"DiN!*#[ b ~:6eY<&sRAGz^h8xL3dc<&l5Y];`ެ8 jg.!/(G臉G[ G~tD7W7IU H|Gm #qט?G3 xD6r4[X& xJ6U1d< C蹗[<*<"o1N`)Tӕ,!°j'|ǀɈsLrwl X;|qyz!r?Bl:x f (>#>e*,L}UigF gZW>25FMG}5;y1U;uLH#B'lLzgx4'QP] @| v?q 7] lǂC$xs]ā <$cq(dJ.RyF4V4kzp&@H q  ja\I幗N5_2G6*WžrH截 \)ty m`uZ "ެ>#cp[t@8~@ Qw[_cQ8ȠLbu=t/Zl!xTf:S (1!B]D4T7F EnWt yYFa{F(JmnqG&)3j>Q%}5yL+MU$Yx|C絜a0Tm0FLľ݈${>STy#jwx}Iɣbwƿ6 ?;m7cfy?#cG^< $ $P]bٯ%vĺN`-mW:~P# & ]4LI;2IdHwz>{C?YRNWU_OW'ޟs^,z<,@͑ a'sX<+F[60rԶ"5 ?9EE\[Df @cBNs*:γ=k=9=-Մ4S)$|m;7WO14jH`Oen'RFFxtx̹~A_+'!kq+ +:NSjc~NgsW#{!e#jS}$`(W(*&^% *zuD$H@Ne 񨙯vjH:)޶\ox2S&5sS3` Ň ÔՂfaD e}B-J{aisՆ&i !ylv ksP~u$ qi؎* aѿtQu ]T (O@=ѐ(M2[3e񨹋e ";>q ;W5rdžL[0+Wy2KgH Cp6k}q{"DȀ>ZI#,Q(E\<`x@>9s!A<]yd?|AeDI>z g;2WjU:xPBG"o@{[?Ҷߋ>落zi WGƿcSʞNxM!{M~g%٨?p[P4$nd1ͩ7:hW|"c1!.;g1Q1 e6Ýcj!wkxV T#qslØ#3 ur΋ȍXp ٭ʴP+c%_b cop{5L:Zu!~@>Lv`tiX\:llRpɅB'2#]x^z@# /'&v|uYͷbjzw|<ڮB ,W mEc.Dj4ڛp1jK1H%a/@)/F #WOI(Gd)NU`L,2Y ?cΘ`1McqqG: e2,H(^i1}G\wQ}liA:Yբ.~q[|LdVORV;Ju *,${gMO1{!}ƒReWYB1}L}_9X_[hj6 6Ud"y$3'&L=Sy&27"eh3Wc[q2<KD!)GqL@3_׉-[*?cHU6x ]x@!G96J,\|C`q谈J0n"jTȭ|(u{|5f9GfN QʣfU&Gavk~Ҹ9lWfi8^<>GX1:T!|X'%OQ!xt(>c2$VG e~^c\NdR!A)(/&Xl( aORw:k7{f.G!ßCDvgs>G-Jv{1"Ӵ M*˴xWG <1j N?!k*ag:00*P#c<7۫ ?Co۹]' $[DŽG6Yť#‘Snqj;G ;jB*OytW>FW[<Îyj\>՚Eg@3Af,y y֐J b^=z._O_0WF}>n ^&JZM/zj?}9٫rir)؛©15G7*W~^YM+> 2'a$3~wx5+@L6{٘z1Nɢ)ًeGY}fgkQ|{)^D\jy;V (uѷ_Uv͂qǺYjfZ%[o<G&TQ5R ~Ay@VONe?ױdثZ< <(y(h<* K 'gdhyhK4;?'cu)Q883O1fޚT#1f"e١_Ϊ ڂ!4jl/܀ y2XГu6\nsF̾cɺQucP @aEJjvpr ܛ uPccR? }%q0MNjwX:0f:9J#~8#"fVVaKdNȽZ2E#PKicGFP ΧMO[Rᒝ]}Nέ9hhxHQq %gr;Ǣ]ExG.4˟ds%A"k*%:yYiɋGCøDV t$&E| c*iqRMnlK)ke!S3c'6ʼnb"˵˩8BuCENؙyGy "gXo3r 2^ 泧ۋ G`GU!SG 8<ʺҴ%hp"+YkDoXom  *qtkFyLa&Nh~LCZTaG9&WI,1c2XC9c D*V5E<&aXt:o(N$v^fH ۺ^N#ث#<":AD@ !)_ۯ3$U3GJαpN*c+ d9S3Uy"yXL>.vP(h4@SV9{U7XKi@xFn{-PEVs1gɂ0! ɳQAɥdX2PwY TcgϤPEŬ;MwOaAΦswHFe*8HrU[IVꐀFuizI=Mir}>S<fޟ<3$ǣc4*-"JwƑʪ#5XN3<&lwvO<٫9&ZI29A2BHGQ v&?2XX=iB4a9/ⱍ,$oڻ_exɊcg6&9>Jd ;XqDgo|"P-tv#8} ?a<@O. #_:{kXW[X%Cwĭ'#hsMӐ&j6Klwt\,Oqe5{Dr8է9< dQF9RTeJ Xi&q珴I`>sS:Q'8C05}WXِ16ZiXFH*tvxe1I:mEJ%1C[)\ѧ} Ry0l\H@g(6O'/L.Jça?(ùfkIi?|ل3x$]g"sI?U/1K[޲,yuîc7ah :B <cl&(5`Bfp6QN~sp_Mm &dxm*”۫}4=ǣ Pm(ssXI)a+q[v>/en[[IQ!Or*NM10nAWYuIi3sΉn{nahΐl TGM U#q*HԄgXuHq?c\U} ĢcJ6Z7X^D%ee=)qzkUr|&PqQ>%`A~V**7ψ z{C!sHX*Ų±XdȊZXr5 (V8  O1IFH޽͌p8dS2Bc5:8ǣ[MH1I."ϟ6sU$KǍGEE{FrjL!}vssC<9`WSl߷Mʿnѽa9?G0v1H1ywQw "ٯ$eM4@lhRoXkz.cozB~NmbeUVM q_-.0R,E KG=DGV Gy鳅Jd&si I{xLWI/g&#DT[u{N g sGGc/ѤWJa,pxLHe,Tî-:rTVnx}N?$D1n~Uҡc.eZc[w,B c2sR{On8dБh+7WjYDAzh'X>WmpZJ߯;sYy@ 7wA!9#!)U5KOqI! ]!`?R {| _Aۋ+33J>{ E 10Uu&-ݷHɣSjE Q20V:$Y?OBTهn `czbU-DZ mpy̢1mQUOl-+ +$o,qw\"ht5]# ke""Տ0UFP@M(N2Oy XIOZ+fsя}~Vn$([H?Vo *؇`C4#h^y>CUCG<52&N\fp|`ւk<.]M#z:J ҂-c<6&k/_Xbw5vZVS?ǢS1b TtrJ|Ӯ/3~z[u (#8IBH?T19J#Spd?)^6ƥDlr{9jSz-y[ON{+T<qAûϙV.v%9WA#@+'Bt7XKn?'-O?`N!TO,lbye7cDuWw6F^X{b1' (+RD^Vx~{wڤ-yi}D @N^cv1]#p#sGSvUc1e$F-^|s.E$2! S#(<MfG<Ƥ_c nd Å66(8uV-SdNn8#"GyDQB2'e)xFC> <T(cg5,r8 k)E%2-B*D)wOQL5X^Majc$ g&@ޱ#M]Er.zs1FQb.ݘe7ꈈ$`׾|BꪽJ8;E&u19Αy4;+% $9BlGr4dH>ؙ QVZL?^1t1_DR )u85yVҏ|HPNU!J$H(R۵lHc"yCd쳇c0|eǝHW5]4 @Dhm?3zZu}mqN.E+ x;?NDGb:)z&%ɔ5NՕifX8*Qo .}Ym(V+D!t4i#$ 'ify'zǫP'W=,},Vnn=EͶ}N ؅xxDL*@7tDeq Z r8 ,VE-`J q'S&]_%>^ChMT_wT Pƚ'Rx <Z"@̎NI왜LaX<^#HcNNl$ <ǡ Nڬm*L\&`-v؁enzH<->Q"#RV&;8R*><ީqWq"ZJG9 xkj#W9S8rrj2xٮJZ,}'_=~b|K?(.fytGxD~JHD,L1xV+K9ɬ<ӵJ%$N< ŞQ$LG5-?#Ъ!KYcg7s,k9*PHr_$ULɾtk:XTP8vc< V~>hZ^D1ASTKp'F $*`YB :)//ROJ蛍UKl 0T韴(ĥiz;1b2sEm2HD ƾ$uK!J謐x.%1L'ء_AE << r`Ep?G>SRK53›`Ťas)V&%-|>^-{P1f^FJ\N#99F' Uk[J*v*ꃭP#9;œ}>?dsh˟Ѥ3~YV!CDMV ^Rۼ0@agx,}4[0yъVAGqy,D5$}aNH1y!d&{5D!3CdHo y\|Q1ōoNy-Mx Ne, կARL'ell38> tҌ7$.ӆ1MwqqnlHUA#3 jC٤|<6[,'ILU~#Y\ߦBzM<)p}><٫) 4;yԁtV18SDp66caY-WYw[[㏷6?SǮ< ˫N9QQx\7e0l!ZdcCV#X:$a:Ӂ;>OY(G1TN+o8ѮmGԓy3ˏz}^q<1E4ޚhӂ<%twW9ŋ`NxNFK.[uIg#3'}Hܪ>R޲ #0 9 )l)!Q(f%;!qC!,M ,g+jhTRhzv^ ˶)D TC*a +58;ۇ 't (Vzl0#N檖,WwliȽ U;|nq`{rR|3F6}h`8dNyMBdS6Sh+Y57WA}43xN_0=蠅lNb"cw$r_Y!@gf$VҤ=}.2"+POoˇP):b,GzD Ӫf)Yo50:w5S-^tQPWQ`jK#fQF drUCO&SxlEɰSE*E&EvdCdeh lJR~țsURK0z;NSZ0!<0 c+,x3qժN0oIMH.ⶑ'ٯ"y'D HAAF}TƵV%w~wI^+ģNR^>+/)HehSZ;{=D%}Ԩ_\~m~)ET%y#{ŘbE;n@QFF7yaxՇo-\CS`\aBxȁo{5KL AC"0HR_NlK! TLQ.40Ev6_g X!V ckʠVx;z17$ 'xG6ӛvI}8j;KIU /X<^Z*>S*y]rQ pknVD T^kkR{s 5Hfelڎ)4Ay(d>kg#z$1V?Ƴ-@FeTd/;J%_CdLFB.dt\M Vi$Hy trcD)##)Qю)>(rQӽjpz\Q l:d/D`됵 d-DT`Ox^k% 垧&9xiIn-^+3cfsXHݝ@&GGȘj8Qy̆G5:;";V'7эiQJu+8&KK8aU_Z8x"Z|x̺۝|rG|bҘ?TXWDa5"U?# =QϲTqBұ{;h4 dIb~>“)B7'bdh =ePCIwkn.A.>\s|\L xǛɝ[cˍ]x.NELjc?Ty˒zyf>Ǟܦ2IE{*o4FڈWH<̈~O \prc:)$oH `"S\a$ eCm*L[Rۿ!$c;I8lvfG-,]N(2٘x.ezqoQŅ}hᖹ%dqB@͎z^9Y?0_H4 Vvi)$t7̾qPAxCl,4S-Pܹ#]ΨeOqPOhg 8Ц0(RE6C=|Z /19:s(E\a/Hy I[~h9%XJ1+pIsG*"($zρ8pاm6% `Px|(i۪G|:i)ť1C@W^GM8#8!"(<6_Qs 'Ƴ[$CC;;9)tcjm|:FEi<㎍k/%X8H"0]8R U=E5gfNE%W`?E"~u-p~f}:19Ҍhx0bT%vh*GMQ-!U 'ToD2,f5/cPh:G!} 1eƀ*n.dZI "V O48HJȆ#qF#>8Ws3J|=y_Gܷ|3yY0=k^.\T(@v.#*`.dT9*hi&hYAӎmgW0u$'bHF*#%HUTT#rvSDcCcBY,a$Hu&ˢx\>RGcfV3آy7Ix7";i8agnN ppϪYN HP$y<-pqo?(toMtpSxEc;jqVvHrꜱfZH[1kgiÊ JΏh-pHJw&ͬa`;JX E\ADzs}cJFy-:H=rUG~e` D\w + F"8as+,zȖ Hϭ;RA B<&Lk#|S@[u(Q]дB#;X<iCB )j l֠6PG=EXGFF7b8GscGҬb|fgٙ{]m\]@Wh0IcDyy>[E2;}`=՛+W 4 -m<3k+ ;"ZA-ƪ)\rT{`ZsoGlL+.a0X:x"攥K&- VH@I>n<=nk83< l&\#9iv(h(@ۦG y@`w5P"^ޣi^=(d??_(pq}bJ@c08K҈6 p Lz8T&QwZ#rNy* `x'wpZ?;e^:' `6UʒjEbe+oΣJ `wo[inl"՜>NG4Yd7Qh- CRzܲfN"QpҺ~=raϹf4/v=:ĤZI %I/QdqF~pc m#J\L`ʎAX1jg&('T+6>)N5±x"} =4gE>&Ld_ jΞ% l8dit^cL\SxE1 滇Ȅ-.l&X%lg3p8ap!tGM >@CڃMVX Ya+FxWМwBg36):vFz߅-8Y-iM$]naූyH#;ZcMUC5 Cq[ґ;@mY;jD;Y  D}u8pdqWarQ#y|ZHRâ1`~>5\adб7bfYh5Wrb9%U>jKH^\> x2Jm}2.JrM!#~QYLc~|^R%yZb&}6`: sQBt5i3Fr^%|@{X<ȣ~<} * D^Vs<f#R6Y3(:gqtV=zXgiM}(͸+D@Rf'R4TեᦒrԚg  Vphb"ueG&c]r^=M?U k{!|cbin~AciNn+8}1]dFywXr\rZ[J=wW5_2+RERa=:N^ uBMV` OdT` Hz{~\ku7TyL4|\X<Ǔ#`BaPgwZ(6ڌ=᾵pyyBކv$]Z.q鼵g}v}O;e-~sw集Pk ָ>?4 w5ګp*Nr[,{WSu vOx0*x}9)f(.8AK;A7)7[}DZD?CbsX{i.s^Q^^^t;| *1Sj!enhVv9/ kΪ4xY:h7XMsB[LʄQ~Λ|Hn=@œKԓ`kZH:iU r|GS%|JH6*?@&?ܿCL{8#]SEYS[RuXͲ)>䚶qͳ}(<H~kʑ87n|c xٟ>ܚ__.b~؇wd??1r\|xk'@ (<_y n݆[wj@peL3xh_Se3~M\}79Do1{HFɕfrjO@Cb]~\~kOĪx&%0k o{00븑EH{{]֞ ,FI}#6;b_~-X,(VЉ*ӷQ$ <\ek\tVt0H5Ǐ4kW9`Fhtݧ֧7n`o'؅_Igx|Cy,{rGZ=_sk-*?F>{GHS\!zBMUb<[:/H JI77fQWVmJpsgB?s#tUXJٞ 0~) 'n! >Jٞ 0~PNG  IHDR*ڂ0PLTEff3fb!bKGDH cmPPJCmp0712OmvIDATxݻn`nۿξ'0Ѐ: 0xIN(`#i"KI](QRfƶmw.xXK238xp A'N88qp A'N88qp A'N8f6Mbs`GfCXsxHk2  ?3?ݱ]>?u4Ϸ?z>?_Y"yr`$aVdp.7?X۪/? ib"yRkܪ` ۾큕e+(-Vp %xĶpW9ۿXȟtFF lFPeVpUS=[NkV~Z}Onh` rnc}:wDM/p֎񇋏16SOn-73&Ϙ?=3;]7 l~'N88qp A'N88qp A'́=㟭Ŝ߯o}Y߾X=M .tr[I~hd |~`u )𿷪▛t0!/%K<Υ!0o=,QXVno=$PpB߯/*D끀~>M+X/3u+O<5Jӥ xW w_ .8*Dx~y*( ؊` Ҍ]_ihˤVB `6oyXk=h]]Z>KۭyrZc{zo嗀uJ W_Xt x~9&xÂef`OWanz`5/;hz瘀g/.9 ?,h=8ٍ'jpj=U 萫&-`V2u`}>3<=U9@}͗): {fH0 j= x_ev]%,25GGW `4O5^zOW xJփ ̊p!|+ޜ`0eD_>by˕So#+cΗu`V7Z>xX lV#e0*S3UxuQ&`m[Bյ0*XpZltH "O!`w,,gC X\{ %!'qUa]} `S,ӓ e3c^Xp`fv X'偍|^AK[K~ xYjjxÓX$8ˈ!`s72XGzVXl? A1lna3:Iƥ3_83k  7?fuH#:X gm޼d ^`6>+F`sdoq V&@~3/u OD=}~[܃;P`m"i+ۿ6>4W^<*^s uFn} lfl}(`s-~Սyk9Yk&pqB`V70Fmi]`d!ɄF Y.*#: T ^sf}m`Vڄ,C>Dp\I7Б}\X y&g |OBmDع2,VIT宵<jD$,`ϟ??,;#0j lqG eHXeo,q{>dvq% VհL19ǐFJs3͉r`c\CtĿd&dp3``s-``^#[iVrל﹁VN+hC;,΄& UbWGjhN] \: F!2x28_5ڿ [6.jv{E<_-V6/1OuF[ :B4#rE݈X큱[o&nfu- Ik`V8k9nHVXԶXVemZv`c\`sUGfk+\akQCш,-{rظ\\pp+mGcۦ f0F.3$zHv`ripU1y=0pv.k&0cKqL.gƯg~-E_A/xB+-~F-z X(`4"\61 `5c\lcـYj91}$3b``_ݻ>9m)u4*%xiV2ia>߶JlJk4յ*=tnQUfRC@- +w ୴JNcՁU-X =+'n`m d^(rtte`1'QgtЛ!C#@-)F;6fA+BH]C,( {1%8RAo1 w:{`޸=dJ2l}A:HDp%7A!`gv#`-a >\C[[ C ~>/FZE#>b|4w{\Lq縭JWhWs*mFF]@縴G53 SeU"yfDpaw8^/lNGV{{rkﶇ]LXx|l\8p{qkFe4H淋*g.j0Cg|I. u;p`{g&H` {$׌:ǝ=kgc}Po̗jGȼwA 4O> ^qOtU > pQ{+lI{9.%p|6fgMa2\T%x1:sd,x]3|#q퀵ʅ,薞90ppQ{B 1,k80>`.j<-]y[.Gǭ\y3XT~OQ\!ߪxW|03؈n_};.5Xy&0$qH˭×k;{<<4wTeίoC*O l!Mg;F%̳ZnVeW/2wMٯ\>`+MMa/LaY1%WSh,+*z/`z}գ.wmv|kDQEɪ|2]G*2!.%skp5&!b/s@>[o  k xT M`o;XJ0+/LHBk'"\+Ʊ" & 价Bia12;{86x X!x8 26j.Qwe;,3~ŕ[ 'R!>pN  K`d.nD0J0v?!5sHS!_h.;fF[ B 0+L \nmچبs*D^ c.K -xE0 F,+FUBFwam~]!rK>zjpQhGaFc{5qWC7'>ٽȄqΓC~AXX=l pq ,NyNqak1+nEW |ʋ.F!>;p+3o%0tʋIݓ3ūUi-p?S *vňjP(<]9 >:y& rynҫ \nMpܼM7x|*֔plܶVM6,!I0SEDbh L01lb;.D"f'_1a$\։ JCm 4 ogډsIK ׂJ#2BPG,C# YθBd܅\NuXOdQ'"Vdb7^w7o R}t:p g0_\!nE"B '4w[OVob%wي~{¹:wgY .'sdH~ 5b]w=10#Xz!`?} (2(4J^.J/m9f G 5Lpf-:2s}2!^ɸ8+~ s_Pm" 2mp!pI \"vt;?ml G ߞ()0A'zr*VwMu]*0nW'vsRⶰ.ke޶_qs:.F<{U&njAS"\4M%bN(Dìo_H~KxS bE`Vj4F4A'N88qp A'N88qp A'N88qp A'N88q4ΓAxIENDB`0Ddq%N  C *Aimage008b0pѭC8t˭/'n/pѭC8t˭PNG  IHDRK60PLTEfff̙3fkabKGDH cmPPJCmp0712Om/9IDATx흻nKKmCy tv~%N6r`#e(TT?8XF%\_d'3lwW_{^9&E"9^5MXj`\#ks{`5F=\#ks{`5F=\#ks{`5F=\#k՚ d`-RǎJHF_!v{z﵌ (nS+ Z.Gp?0.infAK0nh46W_YJw+s`i@ڻݍ\[^|c<JQЛrcY)dmP͵pSFFo`ݠJڻ1~(s"cdHR @  F#>} vc"QIp0 W `1o-wL6)'?`SG=|#ox`n{`5F=\#ks{`5F=\#ks{`5F=נ3koa5 ~·X Pj|!lQyB86 pAAo V"{/0yg3,*|6×½478MZΡ \TCF_ʨ0@ pRF"s6 8\TKFjkUHS w (pG*KC01CKz*sāJSStY/Q(ФpgHzHy@pXwfDS90yor,l\9RTk wB6Is8|ip>8U'b@,P P`Z;1yM/wVE=6zk& )^p[}ϸl-R n `(?rTPP%|MTc\A*)rpORn]~BBDXAu"@{AqaЅ qOj"EךA{ ??>˅|w[-0fEA#; ;w ƅ? 5!1Mt<Pi&E+pQf ɰw@!ǗJL%;EG/ǀNW8Z;B1Pm wsZy. vCf"s;Nyp!&7Vn !'*C)@t~H+B!t[@~kxEr$'+TJo9c|wwA:2@߫.@V}sZ8~:� ,VT< fw՝7T@Iaf zsEPɟ4.r`) |B@} Pk{혌ßB Ď `_ $77IO.@0' bho{]J+AؓWw{ ̪p p 6gtY>btdXIޔj}i*G{|"@|ȠJ! c:?W"@c:5AhHJ7t<jp8uxDd'`FDU<Xŗ<K@ނԗQݥ,@6 10nR縢 è~Ûo6^2@"8}KzAtDs&o)o]3b&@Vӷ4eolK$ $4v6ZUtݑg8{ XZW&ӥ@ [Ht sVP;TI=L ~E5~9Ή ?Og?W WP<@2\X+?3_ %b?\8'MŅ*ȼ_֛Wt_tgO ?C o>Pi_h?Y74*}E˜Lc L|qw 0`]823!0 i/& d x%`<,s+=CWP!4:2@-} &RUkec ) a{{Gs)0&{0b XaL^?ۜB#tJQb 3Mv:l!ضvnXၦ0?SH nJ1!'RsM,lDKK% qdԫ!M@uڃF"j=3P q+c a9 @i1!>q!ͫ!4Mn|(T1E6p!5W"@`yNS!,@E>* .^}bvBPZ&PGl{h*>O2x[Xך1?@[wj:I$}߬hJ 0cu6Пc`PD܉J@zR040˜$z^@ӛ.9ӿ9IE:p7'WkH7"j!7H /t:?=)||a9lLcU`f(0]@{TnT76:<9q <={1Qa>z @,-&,ɩ4%-@EpUߴc(09* 3.)@˩?`~b ЍIcѡO@=zucfz}D+ T ԟҘ>|=J ) KRHK( +6vP<d#DDU^\jZYlc}HcA̯g.O0RPai $֬nύg__ON=Q7\* >%}_ X,@ym V ; HK"^ϋ^]WDФ)j=Ql`HCP;0&,^O*ZvJ;@'oRט27Rtx'F$tO8"(oݑ! Aa;@ `^m0>enbG*8-^•bxr6b/vu6/40Q@|$9*KF(4v^V;T 4 q; PJۈaLҾ20\zKxnFD!,@V( t$$ LQVjCk) ^F YIaXɢ6?9 t0b7`kdqGJf%*a<1!B,Y%ˢP %sn:С^9T|A{ee JRW*s~Dqty4ꋍ;O l)й!!e.4=mr k8&{gq%i4+8/k["Chk8]P|J:VeXby!āXV9aT/淮*/:I OX |q`v+@p'ƩhLѵP|L x,tYy*UvN,6WL1MJJu.dmKۙ8mUU>`kYi9YDxuh945&tix 7 |[T9Ld9@MD{ |JHTe`t֦9Օ6F(NCCdZZÒ elٯ[ʜ^:No t>A'k֑R'-jp!Y= K>[uB-!U(%`"۩G5>B~a&flTu;&m_+W mB⌗9, HЙw"u OO5)ljpBxƒ+d|/x*5R؊6y+l E~iy>G-61+{r{:<6'9>YKx@h)tCEA Fh 7v6A6 %,UZ,T=oDm$@,aW.e(D'5:ldjKM>]w}01&0[m|20L9aBS' %ruj;>W p%FYx6>w-.,G'G֒O+yY]#B"WTf&9aHSٖI{9ˇ^m|ⲂI%Kh`L {9}:v+&Sf#6WPgTq Ó @ueo/⬭rY9^[/fR5}a[HGĂ"ᄔ!N3y^:H`]hAt¡:Γ8Q0*@pB>  XGsk!S ͕&'W`5W@w"ݞAvŒT @v[< ݫ-M{^`F)L #H1&>78+$4C#~ G/Lˋ#$ G;)^yE>n o4v-̌P {*H.R|8JD0|u>7VfƗĹSg߂-IIʄǀk|z%@(gͩyvL{41 ̔Bo3dj7l_MGp#!g|^^H!x>Ʊ3\_zp`?s||yZXbr_ 0v@ۚ0*G2@ܱ]a½Z+hڋ3J4(@eCۀp HsR:GWꋅ=ГNńFa*vA`V_I(ms_8s"qrVG/$P7?<dvҍTAe!KZq3jK'nN638N|P@I ts ɣjZ&o*'ooZO>@Co^[`F-D,&);uP??Udݼ^iǛX %+9 ɟS|U w:\5[,PJL !\]U v(@3[ ܾ rpmknI K Q||>OrwT> n&-lY]Ph| xn Sqvݡ).Ym'i$~w| h)*ڭzSKXr{_8s"Ҍ/F$~:ˣ6趪.J_kV*~?.񝧮;2@SzpyW0&BW^}f|[)8@J[e!-P=X_{Tg }Q#@{# m7ƶ/,WpNbn C&L3g{Hc\nD b]LĴ% '*L  "?3m@sDTm4J @]%<`->x~Yoh9\V&s ͋; RC % ) 3=ݞe]Um?!;W(1,Ȫ;́g|W_BkJ{ݷ" @ `a91IV[gE(vWzNf*6LX7f&0xt%|"4BX0WlV|:smb0eq#ȇPWr~n$T)V|[_ 6Nw&ۚ1Hs6 㩢Or%UWudnM,K̜$pc XѕWmk6[hkQ!?ćx3WS̶Bc46 HsgQű 3ym F۠j6&Ⱦ;&u)@ si9_0 Nh/ `T%>;@*V+x@;Rbx>e.0 ~>՚i_Zi_ Kpf\`6 B/p#<Ɉ]2̬Twq1sCԝQp&_pƢ0_G+YXT-@L)]-kfĖ s>Vd˩7VpyZQeB*U7 !s"ȌCQDe߭U/2^fns ߿߿@O*CX܆6wPDZ@6Zr%60y0 @t0~ϟ~'?3? n#xwi`&TO8@'з\0鈪>}q`@헃h s%3ɕ(50$NGTC DN+LB@J `T0b*g FbJ,_Έ?ySgP_X*V4pl׶53Eχ~yƕx^ɕ%иŠ\0:@~@ jO <@zK{jr0:\്jgq^D;DgXlo k M$HdWc< 1~I}@4-_y!vb@Gb? /'aGicM~\ 'A'$YxSSd+$ HC_:$FC` ]I'r<|un)WM2z$I-JI~OP5m`6iio Gw{H@๬_Xg0^kL}p&.70HK@ePPk;<&(4$Rv/ [PJ m$A#4 Kj~"($%XIׯT1M?ni&G.R4= @A%RANnNO<)Ռ4;($NV8Eo|@]錊D'@UdB*b^ } i; 35Ie/CZJ4KQj|HK, a/&AuKzjAl+<'k_߹kJ(@?]It$eAV~_ s%Tnq1&s6paI$ijw]~eL`rVε# GJ2$p,0f_bRhGWd qfp?zaLLK u%$1=؟6`):H /H\*\ LWbAAho0  0v6_S6oi~Er# uw&90ql#Mn@w ;Dйrڒ;0 S7G/{#DHK 1^n9A D|hu>Dꃾ`r{4@u3gCʇ5s~ ] P$iߒ<_] oK3,9bKO6>z[(K `“S!sx*o 8$ǫz6ڭ @Z0>1 oFѰ9@#_h L65:d~Nt:"G6vi_u,~Dl_^Lh@xhԕ;ϣֲ<.}z}a\ U5YV:yԑ8*^^90xE6?WꦹJNfu_/sFinU Y-hisQ"`k @2|9c=`5w 0.bF4X*Kc;@=@퟾Nd#V/@u?)m_Y`i @:^ *UG^x 2{uM|1DɄkm=0?RbB:$h䳫=` 馾W4Én՘l_x# j}Gt_\=4:y%ׯ]*ԉZ)  ػ{Z VT(_|KM苽> ZMMK.F$NWέblظ}(ҾHZ[w/^W02#/6FX_`2p)UCc/V7<:boN;.$(bwv+q ?h*%K>!и/f$*G` ]ӗz{3sӨկ|9,4_ +biTOr \d/f~9.'`%}Gꋙ_*y]aB6L cU. 6Pm{싙%@O? %྘cUXa@ & KL 5& :@m"GuAClum]a\Em|#Hr[E]Nn:mDv⠼kE^养v0 Rt0aL=<(|@ e_@z5@:Y \1Ct-j*, fQ#<ׯĶHI L,A@F,{U;8JJgh#C oʮ9Kw'ٱggh+%?b#gV+;ZXsI!ys>6pxv^ʮ9om`p7z**4V(@C80mqm5ܫ7 - AD8{X,5mrm `~QP '|7l}zz ׾%Z+8އ=wTZxXks `N';(FSnzZk.'6hv]KzXm\͜Q&k5mB+ihT]u k54^v*)G:}C[kz5K ԸWv;\goހuzމl>߄fZ]}Xܾ8y@6~? еqO8^ ??`n׫+85@pzn칽5@1_CF=pk<Hŷ;5z?j{`5F=\#ks{`5F=\#ks{`5F=\#ks{`5칚cUrIENDB`^ 666666666vvvvvvvvv666666>666666666666666666666666666666666666666666666666hH6666666666666666666666666666666666666666666666666666666666666666662 0@P`p2( 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p8XV~_HmH nH sH tH 8`8 Normal_HmH sH tH 8@8  Heading 1$@&5DA D Default Paragraph FontViV 0 Table Normal :V 44 la (k ( 0No List 0>@0 Title$a$CJ(DC@D Body Text Indent ^BB T`Body Text Indent CharPK![Content_Types].xmlN0EH-J@%ǎǢ|ș$زULTB l,3;rØJB+$G]7O٭V$ !)O^rC$y@/yH*񄴽)޵߻UDb`}"qۋJחX^)I`nEp)liV[]1M<OP6r=zgbIguSebORD۫qu gZo~ٺlAplxpT0+[}`jzAV2Fi@qv֬5\|ʜ̭NleXdsjcs7f W+Ն7`g ȘJj|h(KD- dXiJ؇(x$( :;˹! I_TS 1?E??ZBΪmU/?~xY'y5g&΋/ɋ>GMGeD3Vq%'#q$8K)fw9:ĵ x}rxwr:\TZaG*y8IjbRc|XŻǿI u3KGnD1NIBs RuK>V.EL+M2#'fi ~V vl{u8zH *:(W☕ ~JTe\O*tHGHY}KNP*ݾ˦TѼ9/#A7qZ$*c?qUnwN%Oi4 =3N)cbJ uV4(Tn 7_?m-ٛ{UBwznʜ"Z xJZp; {/<P;,)''KQk5qpN8KGbe Sd̛\17 pa>SR! 3K4'+rzQ TTIIvt]Kc⫲K#v5+|D~O@%\w_nN[L9KqgVhn R!y+Un;*&/HrT >>\ t=.Tġ S; Z~!P9giCڧ!# B,;X=ۻ,I2UWV9$lk=Aj;{AP79|s*Y;̠[MCۿhf]o{oY=1kyVV5E8Vk+֜\80X4D)!!?*|fv u"xA@T_q64)kڬuV7 t '%;i9s9x,ڎ-45xd8?ǘd/Y|t &LILJ`& -Gt/PK! ѐ'theme/theme/_rels/themeManager.xml.relsM 0wooӺ&݈Э5 6?$Q ,.aic21h:qm@RN;d`o7gK(M&$R(.1r'JЊT8V"AȻHu}|$b{P8g/]QAsم(#L[PK-![Content_Types].xmlPK-!֧6 0_rels/.relsPK-!kytheme/theme/themeManager.xmlPK-!0C)theme/theme/theme1.xmlPK-! ѐ' theme/theme/_rels/themeManager.xml.relsPK] 9N`u 0B)#%!4)2,*9N`u 0BE )H[Tp()GPUZ^l4=BaG)L1PS.Yr]5amhm"xˋ)HIJKLMNOQRSTVWXY[\]7'7_b$߅a]_zJԝ<_uT*b$yn}sbkb$Hn(QgW)b$/qlj)RBb$h( S^6k`@('6(  f  C (AMyHTML1"?x   C 4Awrite_latency#" ?"|   C 8A rewrite_latency#" ?#v   C 2Aread_latency#" ?$z   C 6Areread_latency#" ?%\B @ S D"?P   "? \B @ S D"?P   "? \B  S D"?P   "? \B  S D"?P   "? P   "? \B @ S D"?P   "?  \B  S D"? P   "?  \B  S D"? P    "?  \B  @ S D"?P !   "?  \B " S D"?P #  "?  \B $@ S D"?P %   "?  \B &@ S D"?P )   "?  P *  "?! \B +@ S D"? P ,  "? \B -@ S D"?\B 1 S D"?P 2  "? \B 3 S D"?P 4   "?  \B 5 S D"?\B 6 S D"?B S  ?>g?g@gAgBgCgDgEgLhMhNhOhPhQhRhShjjjjjjppppppppppp pyyyy)Tt!E ty#thTt t]!t( tA t U(t$qt# ]!t0u tti9ht9ht9 tl%t&X9 t%9Xt a< tq<t"Lt!t6E }t5E at4YE t1Ut)UAt3= t2Q=tlY!~4-1&U^ t,U &t+ it*i t !4 !4 !4 !4glms~  ( 2 Z b  < J r ~Z_NOSTZ!a!!!$$%#%& &/'7'''~(())**++++++,,k.o./ /o/t/0011?1D11111 222 2$2-2a2f23%3+393R3S33333]4g4w4444445*505A5777777r8v888?9C9<<<<<<?=K===0>7>Z>a>>>>>M?U?V?^?M@R@_@c@@@A AAA>ACAPAUA_AdAAA^B_B'C-C1C7CJCJMMzN~NU%UcVmV~VVVV``ccZfafffffff2~;~'*%,v|<B@Fv{:>%$%''''**,,/ /o/u/112273;3a5d5e5h555555555666667.7/7]7a777r8w888!9#9?9D9z9}999999:W:^:::::F;g;;;< <S<_<<<<<D=K=l=======>,>/>>>>>??M@S@@@PAUAbBBDDDEEMEFFGGGGiHHHH#I)I|II>JDJ KK7KCKKK-L5LLLBMEMMMMM%OpOOPWP[PqPPQQ.QbQyQQ(R,RRRRR*ScSzSSTT?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefhijklmnopqrstuvwxyz{|}~Root Entry F@r@@,Data AL1Tableg%?WordDocument~SummaryInformation(DocumentSummaryInformation8CompObjr  F Microsoft Word 97-2003 Document MSWordDocWord.Document.89qiozone3_488/docs/Iozone_ps.gz0000644000175000017500000100103013573734166015316 0ustar cappscappsJN?Iozone_ps[sHU&u nq8@v881dI.N KcG,IǪ}Cuu$Q?n'+'ƞdccY=yrdK4fc!#y5No1zr͏=$dG$d[k~ A%xfsCimlnIxxdM< v*g4dZ9Ne2IAfH_^ꁜ&co:)}4&GCӟN&a#*lPы7j37l_v_a(#7Xo6jx&XOGn4B#y#5wxLKA39 }9taVE^/^ @fEW뢉?z_ib(bG Ps1>]$Is#?^si`ʼn}Z&2'} :|H/nz7 2HN})ˈڙ$QӉ'Ie &?Adk-Y+ ʜ,gz ^Dv+ݦZ"8Yc$ "`EΌV$GƩdV8̂u|;O(0/Kd$Նck ˦&j4m~;D47R$!6Q8SV'ޏgVzabZs}X}aGYVR[YWE1UJ.«♺<aJdBU߹=c '28lV -X"ga%@O_uAM9*^[mAMy aF . )᜺7%r@ 3[B?LhwXL5Dĉ,_u =lhya 2'pzfxDP"tU 6Mϑm^h(\BDDuBo:m^+hӄ| ەUkFHswXfH/t1cweS8I^/rDn!anᇷs}פ8'"ڜca< Kl~fJ9~Qr0󣔴V< gX zrp(ruM.>=ym )~ȫ%dqj,쏦8[ EԵ44n $0_yb%6MZ0ɽ5;dlڝj>j|0fQP!p7*b˗X>b y\S;}8N#mfA>B~?>Ȏ ~5H?g0 7 0, qE c<]:#(f Ij?׼ тa4@43R b' 7 B6d]"X]+4"bBX׽7l/G؝d j6@i*`#T!+ oT r P{#4#ĉc`mq<ɂqDF; 6_ 3P5 6Ps1v"L!= f隰M[` (3אz:#t"Q-&t›-% 8d-ԉ-,˴qS=q'J:ŷfF\tH˒)4Sr< )Uؠ@H;]$K:)"-qXVp_r ı7!OWo4l3A] w~>~\] "pTsAtQhoj|w{Q~'-CL P!(UCM$% FX9w!(< ”Hgy[fywNٮIm\&~ ] _2^&f2{JHe[RM\S V,$kmh`_3+q?8q*w@0t/acBAbȿ~ ĹB61Tַ_Afg")tCP؛)/&\}Τ .3h;`W̃@8iNrEs I)G?~^ ؀߁_&oW|&\oxfD&9,oc|( ̱"8w33o.TxA27E%~_bxF=QyJ?Q"Ҥq'45˹/+Nb\ !ܠ6Y[1гa@ÈEʳT2qfLws P\i^1 V"E/plr3~"ǹϠRL!vmQ -9@$:1nvSJ}|ʁ21Spֶ 1bۧHXA dr=} `Eio-kEw%bkiX:Nxعٴ>A ʱ'g/m n릿5hCjjkF깊'@zMefB]a/PhxERHဆ0aKŊ.:LQV#MY B;v5P K%x<ㅁ]6'W 0a73j\/Y|aɞ*d{ѳo0S oKsCcy^9pPduOG ;U$ SdDIqU(Q31Y}w3TdF;z^Y2WD="fO̗*65^*D,ǶBmp285A4}oV.-}r.gqBѹt%X?p|ۜ>V~T}T >O{gk,;/7O*.U*U1 6A~́hPP7KK1W7pmW VYxSYgm뜓N^&u(FØyO`y k_L~tL)Rq 9!f^p|i˚%Ĥ%2Y|,n!O%UTgMt쮵X68g>h6ݛz-Pq(A?MX3w?`<;nOj:蹙Z{aTV;!Bv]Fb``Q9RC\_B ȡoBdΆf!%rWi9<ˊ\)u> :nh;)q Umv!JyUrN; fUy_pz-[NI-!wFW`*.UF|Q(#L+*Ky'*V!KH[t/;_c\ |Fop72vNhVl r`CTs˼QS_RzRWCyY#nEWF0>"^;{8w't_\N?~qLቹAo< ģY5۹^I?r+!JCدwnGRoHvI?-򐧕^|D>Ɓ)W($ȼ g1N&U3~v 89F(sUab&8~n ^%,WuPMRjur 4L^=#gv5`!Bb}P4P[Zs VevRu~V"=&lv4겷!6\-Fبݗ 8A3$WZYn&ŻNm"8m`)hC m2"QKZQ ű%AbA]Ԫ\(>x.tJpXtf3 ۲(^=e]GKѸˆvu|ֽ@LpoJgS}n+bQpAUġSs"||g,Ihj7 I䇬ܯCt]J:ܬ!]!MAJ;OEע4SY@\>l`yI`@ Z9fDΫj[C%VQKUs¹zmC g1o?*}ZŻ%_0#z]ΪX H8IP2˨ Rw黏?II:w%D=ȷI8g^ .F4`nl - y旊&@VŁ*OGjv<6QZ)T+IAbdY\pv:V+OoK D^"EӟR޾N^4,'[]FV)^,L=PT}yځf'kB a$cY_gU%TRx!9iuZ*J׿ΐh"B5$ۙѺ34'q[߫o/U`.:,DkM&ϘkFGS^$JMgsV D*hxz're飃.NB:-:}_/׍|4)-= @_5R0鷣TbS|KlX빿,7D\6,,/5%|׊= ;iBg4)"~WSӁҜ= U ۊ@av2F]H‚&_ /@ Z@:N+׾èܑ;ib#olH (PCr*RZvJ.N9~YfQ ;?bɿᦰ:tҫn/9i-V#jyg 7=u_h1tE0 >:bm&z=/t¼n-.L^vP\$dgOh[D=Yqtk[x@nW[`zvQٹT. d\|9:1񯻁LjCվ<[~yVS<;EqSFG 3@LcǞ/2Odp,/p5-QcR$7Z>JzIdd.N0bL U _ӕlz @GgGvuQ6a;LzG=vKl&F;kmZ?NwzEbvz4?0w7ý70>n=o܂'ƐËeCՓ:p6q-b{jjAHh3="X_tm}EV]`5ắ h}Yu$(E ԤntۛPE..ה?<ޫ)d2}!=M]x(Xgpr?yh}֛@Niw9:9/ոi{ܺ5fv;AB~_jOj Q'H} *F 7iHh|Cg6jxm.ze5}\FfrutlR/W6Gw먔顶H?-ж'4zbw~w vݧg-<| xHD1܎VN6@$p?e\wep/Scwl> o(O{r0E;!ȕ}ЗOz P{ ׄȬXҌ6Cg~||&Qk!ѿKMp\I`.\مf_'ș(Aܣq|SfK2u7%K҅ Ԃsl--k[o ޿4QO34"0?a7˓fGRZL{1o` oi~AVsBڐ N9#}>_/O:rygddQIr pXu{ʁ.Ѐ;PV pk+`̔cA@jw XP6}§OhO9Cat򽏠)?UO%I6Ԓ|mvj4;Hw6"Iue:]ql5n|coEy`qJ}$ԋ_'1RQ$y7_61ѹ^Rݦk r\⮓Hˎ1Z gpSF ٸbps[H8MXξ{~ v8P=^j= 﫿8O.ĺ0-0J*rn'ϸ{r*xЙǪi8ϏCkW؛c]B&Te4.Iԙ>i+Le=}0ѷ|hcטcЩzjvD{L4"AbiU3eC}y֛I?I:· ֓zwxl9/\dQD^R2b&Tb0O=K(&!&꣆sR*7 YyާZLp4ASԄcGQBssuŜN=blZ1Y+ZZbo# q&}GLx|X =SܢT)^?`TkB@K~}*l<%Ewuxe MP0L$(Od>uuœ.2KsAۮ N1[p~dN[l&oD׾7({e\͂ h1Eh楕NNtpю>R:,QR~U'J2 Ӥrh"m &\ܞ 0iUxJ.;y1BW L֯żxe')`&T_#swuppaUF@uX8*5, rdGڏ;ɋ_?_qȡ~ms??؟ǡm1|%v.Ed bFՅ xG>d 6wq rJoư{f ]Â_~nwc:1pN08$}BP!(4~_wǙ85-qbAˀeqs^ M/ sjOڱL?y3eBMS{}sr"o{1IsGv6=j>o"B ]C5<5'dS'@2B\CORlCm bbv.<, ]|=]fAqvuF)?> ncW> (4BWM^|\ƙ YB¿rEhwӥ7)QPnd#UP(.ģ3/l`w/Ͽj 毻(kŴs2'5׌݈d;n>{s^R.` )h5wxlc6Vį낓cymx ִppW6 o#*k?'>޹:+Io*e1!iWagzHmmΰWOTW@0>8-vl{c4z@*t,,w5q4XY=%VELCwSor_-\h{f%\vNjbk>iz`u@ MsŸ{{&waEYଐz֌_xI/N彾iR5BQXb}铞}*@)!Nb"2t%Hl n䜄 *!*|!/W0((O${SJlJ ÊOݪ#Z 5SNO]Թ|r.RZȯ@jAƦS8`~iO97\O +7;LZQF]ou6]ouC;tY =5 i"@VzD i ByXGy }E(UP !K 葠!< B!+K葠4l`V"C0!Ⱦvf%/;I;Y l`V!C0!Uvf/;;Cd_v٢&d`vf;Ԁ lg}! ̀U:R"݈% .laȾTvSj@eW݌%Ԁ .e+ KP-ٗ].IAsK8D]K]¤]J].A%EeW]K .T79 ~cM`4G&VANWY 46YA9V\-fzӫDhZE/ӛP2)ZuFR*qQOK*IXP,?I0NFoZnaL*Va"}`%I&8I҆ Fa$FSoOF>Lrf &LY#@" I&Ȕ8L?6L0 #P"ԇ aw$mq$mIViG҇ am$mI&XBsg$}`Q8F/6L H0-6L ҆mhzC)Ȉ҇8E ҆ Naء>L҆ NQi65}>xE)*m6Lp -aW$}6LpJxE҇8E ҆ Naء>L҆ NQiö4dMZ^QÈWT҆ NQiH0J&xE҇INQia[l)qWT0aST0)6 Y-+*}I&9E ҆mxE҇8E ҆ Naء>L҆ NQiödMZ^QÈWT҆ NQiH0 a^T0)*eI:LJ&8E RcMZ^aWTR NQ)H0J&xE R NQ)vU1&-H0+*NQ)aS$evhyER NQ)azaW$uH0)Kr Ef8ERz.V|f簯^jY\*>s9EUYňYE $؞-3` #;c|v*}45G0!{lb3 Ez~M1öÅñgGސQO;]y۞yQ/{f?۵8]d l>Lzݓ*7LVyҤDX HT\a 5?tuZҍm|WliU1{_DUyqp_M*"k'^gXFaH^#T 't& gEME:CV5snF5mNխЛ3-Ѵqmk6Jy#Wl>g䨣~J>ᒏFm8}\BEAoyB יf9bM%Exr]NhNA"ۓb6lK5m5=L;XMw,`,̸?[ߏ!/~;v{rn=jᾬ{8Cf{k79Mki²XOsoOa3^ia pKxGRX x!954P3ɡgJV#Au^,Mmy'}^8jU,>ߏڴp;ĿE-Xci#  FYB {0ag8c4Go<9T>gDvPv?)V!Fیy\k:ꈎ:jv4.4=zz'^{}z/3 4# cX3հjG`ŅYxuaT L |r?Y'EȿIׄMP$ OZL@͛ *EU_eŘ_?e_׾se%f yj+SM)J~M¹^xi<0\ͨ ji|`-uMCCȒ4W̿Wb :`oN߉ _+Ihe `LxZ)ϰϰ4M4aKSWЭP==I[XdOz?(cjoZ5K;ReL;'OӏcȯO}؏} 3F o/.5- R=Kjx \ʊ@.BD{|<Ô?>W}un_xcD}yY̝y(yhy hasN/͞Ts_07 U.3ͽ(\0MaùŨGy#9K!ۅ%TMD s3 % 4NS/(x cyk 0*WɿObh~˜_w}w~=($NIy)%寤4ؽwRM_I7X9GVx O!Sp Kl?% ݒRWJ zoNߩh_2Oߩ 8}<:KO q$VgM>B;sɃ9?j8<~IxܖshF퉚Kjjo@6 gMYqO꿧9UW)#} {n@Vn޹꬀._pQ%)nQB^an;1W5{4;iNqzE[k mҼn5>!|z9n['xQ? nT gL/ j_y͸ڃ ],Zet/+^թWp\׬o D30Klz{RK)WaYW3%etX؞K]5Λ"^7>=č3pnӠ{.O =9{@1XY C@3q:3Hp&Esw=>4KE`+QUk: =[{y%` zOlҝm. G fGp?EU6S̘ y_}>/?IwOP1bq5T|u&1:+§̰3ꕂg"3Q+ 7 *VfhXJMh;*^j6 ]rz=gU 41I=֗+&!(d7XV}{w@^ [ :b)=Ju'&Zۮ _ %0ipo0 [ (;Pڀ`4x Dl #||MF]زq-ng7n?'8^؟~(xݛw SZtdz>6ДߎBje) hD0R5D; =VR=Oe[*M Te_]TzXGv(0R&V_rĀ?N`!%~<1O{ϰ^<>0} UUG>?7neox)[D?i@ލEY^ݎhEEY LX?b"^vlqg-L ~ |QTh\hb"FA1b}UL("iWEqE + z`{;Bj x_XV:OYrZd.^IqR6zHzl$,vs mE/ͯPчDfEd.h%&.+{C?nΉF5Y/ʽ҄טT[HFˇI,VP?xne (O=S> TzAب Pv=8z>e6)cR;fCozs^<}"Hl`_]q̗?-zM{x4n|psrNi.ND0Bo)]V }Ew7ߢf|q" g|?3~ hZt$ZfgouU购cb;_lC[JzZE9`'' 4:wv:'4mo.-hbխKý0*S`^U 53m -%zGux8*/y䷭vQvo|(%ϡb3 ;g0*ΠgaGR0 ym_lGDc;[&ȢrJ-=1 ~VM*=aRRT>]856uh%U\AHYvZU0IyjnVZEo.GQ ;LT.IF}u=x_a5rٌJRU4kRayy|44NxI#b=3:\Dr:2I z[tiT Z} ́ϙkU_KR/=ACU9܌/AI^;r"g3` F&۝)Ǵ>Bpq+q[gHǏcDzsr b1~UAQů;@$‚!OPciX# 1gh/n +'E]sTLT%qg2ʯۊ"Czh%}L(уu?h'r9LKKo=fńmFqo3@b}o?Xt{>߿?<~?=YP@wa:݄mt2Qo "ʊ47c2 vOWA#I } ,4(|YO][X&!ޑQB #2@=eU + ;gX7!Z56-o6iRZ gM66ǀF=wHjglgA&wQd큰b7D[;֜W:f%5 * "B. w6CETYY&[[E;^nYEQVZEb Lb K[WFnib2O¼6xwfSn oga6>FmQ;%YBz))+5~3؂llmlUSAoUV|R"ppQ`UՂWK |7Mvr(`U% UQnU/>_g6`_h,7h#/;0.D'*xA}7h"nЂ$g^"pqK0A S4qy'?Lj oV7h8[8n| Vzy_UDYQPY90e AUEVŊQ!(߭|g`A w#!%N2* (ؔEUfFQ|n]jmoRl[0--L/*!1iU;Xڮ*-$xT 6-&! w8)tQvm%BEmG͸ 7rPڈ=E0&CW[m3@H=W;p7{,"͡,gHT@tJqH#:[i޻ k8=ynHM,d6n$m}=Ήa0AYp<.80}gڝkt0!=MHP'9,UVG>gyf3b CS4uq$W C2$aBsФIN .mr Vۛ"AVq` Hh^Yv*$hf33$ ͬ4Y_RiY9OYzC:Y•+ZvƂDYB-,kaD3ZeL YW5J2PR$谷GAHq3[S]ӺT¬f|2UԤgxVN[-Xܨ *9&aK_`ch[:ߕ,/-\l ;Aʇ=m%mтxxjs(m +wZedJr,54vC*!ɮ眚=`7(ZK%i/Fꌒ  p@ޏofx^ L#(Bj\M( a9]'sqe2xUߔ!*3ᒫ$iu|kRdO4K5$qޮ Kp L|ПsV${=\CZԊRO  Քؔuk YXTv,#QX4*M'gPި=j졷ef˴jDi5# Վn=X#Io4JlkA1S,?zc`FŲue}Hi}rU*sbi8>8%ܞXr/<|}6S?V)hटEUbХye-Azry13\T)Mftjҟa<$c@)q$3e*axBgeU26tB: aE / Jڝff)\)@mżls^#ffeYc#cṭڧHβ0w}z`Vq20V;[[y;ڬm.[ť1)n%Ebl@wv|RQFE!/+b(0+7(* K?|JMc1JӢHv72,s+ҝ0ۊ<>[W;8&e^kzq%'u҄M}UJB=[?v>Hl[QH=y.C2Q^x`*`Ap1hTIjhry!bFR"tKǽ,;Qkq̔Y[`KϕWlg?tQt?- x%{:ɽy`(c 2z8юƕ|W0:mrcpFvK7k1"OB{#3s0^pgAM m/q :~67h5I"+1+4`( 9/ĹnxZBy松1k+>7;"SQGA^RPbERssti Cz5/1Nk*05 \j9.y1>1)/5/ƛߟiEY$4䍿YM<~uk#yf4*7Osas(jr]ַ=b=h ϲ>夜Z{1U s-}o"W0coH7[.f-emHʵxgbW9w'KɜVtđbDlvc'*Ĺ%(AuT"$UrX;yb}?aVe#AWR44$F,{Ⱦ\f46#ԝbb^7#֥&{0Se`20VqZt*^ݪHb#&Fꈍ.)µnjkNqb@UKN7g3I}GOg2[28:"d)&&\jG:$p"\T+cI +TԂgH%9/4` y$OAB^A5opsm #8Ev ÇJPZzĘWQi"يo9Uf'&&7Jԅ,%" `92,}N+v'7ZVyxyW$\I54My6]lbPqE GgĦ Fb:1)>"*JFq̊zRgeIYw%I54J٢ 4g }#Xݣ@j a'%)VGLp^gBl XygkE@Z. 8}Y^h$Qbuك(s負,:4/ڎ 9j"d9:?B8^ւB0FgU=^˄ridӫjWGa~%ri뮱'Ȑj~5Zl$-puz AD͑Sa'C}X@'̪MP{ςjf4FtxҘ(`YU|T~͑q )h&^R$۶JTK<6ck1 0/PNX#pV {ݾ" R,Á'gQsDS t",BZ:!WyLU9S3[ݹ K%dAb! ~F4Wx,ֲ^˺^UUC# hIMU[B:xO+ E-O:9Uo</ j\9NJȜ0=ZJYm{GTbwGXX'R\g|(BE+- L3Z5#h*kG}UOLSu0~'ַh=D[g--ʷ /ߌbR(q'aVhVj@*@޹W8D&Omwl& ZvXw MGޒKQ;tjEl@bltAʹt%K:I%8Q1$Kp2 F9T?~쟥vZvzbDԳ^-qFb9?;<2Ȓj5'{QfWpW]qd7G>8FJX cVDc!ʣ2K ?b~mmi-"R%UΔv)ѱj19Y, V8Ш,&3ʍm*o5WAHD{MvڧjGEsM8+^ۍkNea5t)%}!>7bhbV $5tMPQW4&Qi<+)2u%;)$21l$2]rM\qcOʐToiz.YiB!HL!3&_ިӹ@ajY0Zkٝ1zgJ>BV0Z `nvv C-X \Ξ<b$[|9/=RIZFVեodِbfjA{ B`ZiB H} є9eDpJ.qS< dT4~:>&W }}R,ZS)c&^{7;nvrE5/JK7^dcx²$ C dU-PWJ2}mSnMϕg\E0X>O-'Pxk3 ëKGsb_GC"ѕԵ,ҫƊsup3eutGfzf @&7>G٨ނay)UFwwPc3lj2JA˗82t9eH,!l=b 5OsXՆI@X鬔=[k W:{?^*.8E*iH%98xŠxU-Bh m9"(%zoTpO/@|ezc0?B& zzLL%Ȍ:J'e$brnr˕9 ZlxՊ4s":ܰgJ az/OTjPȟS V̪L>]PvlJ"b)e UmIJ61(4xm8!y$nKydɓ1.,K/J,3T[zX Q5Ql-7X)yaJ $q!v$g(ԐQfX* 7 ol(΃t6s}V,f?SAJ˽ aPs؛]pУZ=!=N;;J]8;H\{7MAbx̀!t/?)#Qٖ"qxV1QD..]Xj)Ey -\(畔.wV iXҨ.yJ7;֒~Hs&_j\YO#CQY>3RM;Cw!3_sXCgq3"SRԮQخU9q2c,9 h<<Ia%1}cq%KfӘ]&q,ym?x"Oхs ïo=OSLT b@S\xttnA('(ߜ虿L@ zTCJ3Hv ߊ^ 6FW%fc tUGNr|O:!{K%yrjV)WӁ,1Z+u#e\HcRqNJ8 54o.}F`GjEXFڄpMi1P˵[aҙD6ҕ-T>a)]d@+wN\ruև)&72ZAc.0sYF fs^猟:WZji~J)ڧjUS;1̏7zWkr\ڨx a Sqٟ4Qf/̙ Pw9"j<+oad[o:Ff&m8b|tTmbIE]}i+Dxž2.$V 3zb~]k8\No|#$%>7̙L+3]XMfZ%M:mto"V`\ۘG=ݹoXYK$c ]3bڬFT~ ^ߴ\4&7Hs/Vr6cTX.c+C;u\-~Ӥ*cJ{SQdorNJa$Zvfm(CL(iD"nyR׷Q$8,4"نQE<7nKA7k/hTrR&s$u@۔ FF&&Rr'4[#*iXpAmgTyUNJi@}t{-U e&rK=r aouT.>s<;qtZ.S%H :3ȥgZJBt'=xGHQq,NS:6fU"56?W,]CaSOnݦ6ڮv)arߐ+,+#GNƅҌsڔ8AoJ}e/tPHH;L$X"Kխ8[x)!r$$;NNj9V&P/ ! 2vu&Dv*)/u2ڈ+63Nƾa!ٌĚ2{fHk5AIsdd7 S@bMy-?D>Us-Vl6kEHt@Rǥ,AXrP.8Ǵ3ͬ`o0 L +-(Φ"_oKq=uJ$Bֈ"ǦvvFMuDq$={sG;s$AbָmiF=PrnF zhqRn(b$U1u Lzew\$)RR !j ǰR9g,km' kNE*U:[V{O6%L{ɺf2m_HŎ̞[(Π~n/W bYy?7rYSfl*TShNpt0gӹVp9LB2.ec:=f (+1'DtR}YDnS4a߽2gMjIҵ$U+~JiϲJc|fb xB]ΛY(=X|T玼0ojbSwrձ*/޶2fȥjz^&B=,41+e4 &^Z;KZdk\-p>W+H3Z9=RK OZ ~@W[qvݜ:p4]^4GK) NddbUSИ&9oj#Y9Zl6VrNNr#aqy L4<2II/s5vUD>qStE>WR$>mHa :P?ALrαq̪7Wp24A0SjuR. luYF6Tl3FSycd[zG1rѪȜcuXn^L <OU P8b,o<%h#<[j5]MNqƧj}=ޕ}8rۛ&ZS<\Tˤt79d n|x= &ntV%eu'mYlqk)[9{[xo0;n;‚ΰ\Jڱ7N\Wb|Hq0UۗdYMM8sL$Y -fvty&&-TI8iX0Ey1#jөEKu) l8^Ur뼫ARaF%ihA[R#o{fE> iTw^*$q5㇖eZ MQV/Od&FT5 _Q\`Zܱ!ױ=bjr2)Hz ?HWɌV62 5K9tRr̗*6RFUŜP\\q65 i5C!G3Ē4Onv&!5se ifd<n!tL, }Df,>GlOrsĂT! Cb-dY'\up&WzՍw<Љϥ$=|Py?pBɀL}.Mc3.lɕgaoxc:K8H@Bl!y3X}trQUϴ4p13eQK@qz٬Tj#2w(g8 Yf1vF3R>UcQ,߻/Kuّ^)x`h1zKu՚:Nj%튰r#rA#Ō¦btbΑY K|{,Yx.p~28VIMH, PuSO 0/\1鹕!%+63f žQY!Ay9HRUP=ȷb6'~iOX`ey$q0#oHJ³"n1GoUQr6%/'Ip&HTHTIJ:2{Y35C@H/'kgEi*IǧST3\&Bm" !Hwu:jx澨j ֡,2Tq3Fc)p j)ɖhV$Mh$TWq 7b'px<+ [zv,>aSӰYK|}[A#4f-c#'7о)c+ĆЌK" XFs$ޡSh!G~0 ﵕY9V=|z7t2Qއ@YTo.66#Ɔ2tUf"ȅLQן2KMff:Dc.[bt9øTXMvO|$olV[rg9Tڲ!-nh(eA,5FϙA91nh`zB+ycE2%3׺]oޭo^OٔLm´kL~GDVD*YƯEraeW5l^ $0n[xɴZ"+O_0*4}l"'/NP;~y~?s=Q/D P:jB&z^H< y9П9^xN/2of6)6 ne |k5c~{M1zPƷ8@]儳TP&*,*!!F/:(Nɏef%nR%Z]#u=C-e[4. 2f**u0vJ̓M90RX9yoqբ>y쨌>^nfQ|-poVV+BMmf$Ȟ ʍ}2\vk{f^`1tÆo@,u @Z~wS`Ō?@մ69D/pgf!w[|XkHvc PA"FUSV u|wc6)gvE[nL$4MSpd Ur ۬ZKt͒<^_R=6x^J ^91:QJ( Qce6.(MCAwewq]3!v6%CKqNa=aVWPg^smr@$>SJW, ZjEH!I fRM@|7\1l.9ת0<@|ƛ1{% 9~ʫ281z<^PDL@,me b` (RkLO-V)aW[ՠ%2²Wx0$D6JHeAd0ѢiAO6R<67CG2jOv(Y6]#bIXsG(7G-McҜ';⎤WJ%&ctƭQԜZ+tfvVN8KRpX8t[67r"پY1<:ri07d~rY`!mx"yoaZ~+2/'*A/PlusZSQDt7@$,et5d)7`+$m6CgЈE0&LM(Cs·<9N%$] :HȑbOvG_K v*=}-2x(Xf hp˰Xe˯6}8[_%iuh"),NS&?v #/Ðays:VRn v J${Gvgjb|1t r࡫jn ~J@˥{8D2j⩱6.s!1l<%# Hhd IZ2Ĝa.5fƗ,TjJn*-bT֙ 6i @7|?JA<w3wJll$@3:=0ʴ嬉29 ٤Z"}쎐d 3aV &fBEVߍL!"^B $:FIMþ n` T$Y\ yƆѹ.3xr{ղ9:s%.ߛFfe-tv T+b"XG])o^Ϭ4iv _7d{F4ҙ2mh'&8,SF"2^x["?UpxS)(M8胐;Yþʸ>5Ƒ{VՐb&x#`M}Dt44>:gbT69ZvlLNP&bKtV]knQ9pNH:nEj PnEDWl*^U{h7)R(V+H,+s_XlB@ewAKnja';;,B7zY^E/kbr\\ Mxp#DfSk7ERCLcԎ`Eа3TfQIsD p|:p,$ZjYclyC#]uy\6N%5a}qsvt}t{L}Tۋ vxR;rU%GVQfaJ 0o_BKV֬b/񋭣0 RXX1`P׃lp|ˑOY/׎g fWb[K[VzNV쑣,OtvКV0楓c 8>sa 0Y7uP`Nf&FD";v0l1{<9 "Ոǩ CRw\ L)7q'\ؠ&>I~*LJ[<!8g +Cs\v}Xbרo2> N\BcQ9y_g<\,)ؐ 9pF-Sƨu ݰ][v*@<ʤ3 qDN~<1uu"]I$VUJ `d@$Ҳx3R%EFe{ --c+@vvځ.ruNS΄Z8cs%Is)#ç Jaun(w@%n[ty`u?1 KX+ۭ,q i0t58?&i}ô2wON-U#{ΔlCtC #JBTd5&cڅ=E-+5W/[\Ta(v (°MҲ3iw$$85&/yeZ<+dyV:ˬeN3s#'s>'t:ͣʹ̌K-8fk1~>b4qZ3tRgBsBDf$PyHrTy#uMuoOF@d%TfDg] ;}ѧw}'7wj܇=j?~L̉l ު#)B1SS=2C55tfyLOn7Q[,IFtĴ,gp@uCMVKY#^2В\t%^VJ.d-Fۤ׺iL|lXE|cViiZ ,yW[GDuX#h 0p]@#feH d-qQx!rl͑ei݆ |QTjqob(:~{{r@7aXP RqʦmRBGF"(bE:L/e<֡0P{qH)[BlV Q_򔰂#^ՌysM5ƦsskT12(Cq렸n8مo"ɏn?hMe`pl-x `9>7bIf;|&=APgIt0aL=>'axJшADeFt5=Ugk\ E- \hJJ:x0{Y)Ge.4cOYS! OIW`# C3 18c4á`%ҁ@d@q&},k MZZ /#g[c9 effY(@S;arٜeY @wUHb+JXw*Uհ=X9G}TR=ѿKtE< (eTDjZ(p%TZԕ%ԪsMǏ0bXgz+vL(M?67*JTqS2}|zSyD*NBsy;VB/͍cST-3/ϙ>b6oݣgiqN_Bʓs+ȾTJF2MhǤc!),Gp}/ ˯DVӹ܈xۯ>!s[)id_74 *qnBP.BjUVf3rj].:(+-Y9*_Թ҃:Ut]P㤢 XzJeߤ_: ycL̙)t-VeiEO^:QCspa-,H='^%^ `Ư,ͣg ?2AgXcBIv1aD|Ŋ5.gQ,y53aOnӮH %T UE*:'aCM-ξ~9!s@Z=zǵ+b1UZ %btYN[L[Ε?˾&6VJ'؇NW9rM:p@zGY3YDc8 -Õvaja:2bnNOu~2 ڿrnq% vet4 / WQ:i1H*TGX3x ^ z0V5b/ɪH"V %-pyˍ'b$h2եEK 9a.X>h$5"8rY{gC­C%4AsÈ~v{NnU`ZyC ?.|l}rEl4[H#cmP)&Xȫ"(>E^}yW*jOE‹ËbC_{~8UZ;D;z57 `#>QwNpZ6͘73yJgmr" Er0\(obLioB.7a]K̮e87iG-L ]˜%$ztʲVHd:ω(b+n]B"eattP:Çf.g6 ĎZHd,;ӛ3; u_NZrG֎ =a]kҶ< s0[CLu!z19NG`VKy: 1=r.3Cjre*Xb=mlCInf!v܂Ă5ІRy3TSj;yarSj."9r i(y0t(㎠&L +&ld(pDGEK.}"_@GI© Ų8Q{Gu}_XjR@X`0U`*7R- 퓶sZs=`!yJ#[=LHN.u&,O/?ak n=/PP1 Z.iTÚM񽺮G+@+ܒ2 bY2>"ŲjQLz{hJV!RNzS&AKkRŦg33F",ˈ /JW&{V]92N~&uZp"3Q|/Y?Us|*jm9ǻY'f"#DZu(p42g=m&;X>lUQ”kp0j2理>#^P_-~7LK,4ɑ]!|΋pL'޼gѴ7_LZp qnhQ0U䒺al7++#kQ&'GIU/!ag aO(ŢwٓPѸl C8Tqta]ion<+CW/RCE9>ܲɒ mһΐjʄF +;Q:\Buän(5jEghMS lH:sڥ}SiőrjqYoM!ӺV8Ejp~,j_K%}4\TƴX"pHuOHPH?)Jϻhs\͑#U->zLOr{؀2fm$|wfD* ^+OOPFS\Ҽc,-cv0}Bh#ٛq jg@:g?Z Z* .)P9 }bD4٪Dn$E=8E5§UY ,OF ?/ 7QPFF,Q7TbO"6 f_w܅[+j҅,QI&5(4E. ΢dH\Z{}NEPMA={:-dhEu&>O5D1ث䦸3ϴ󬛮]oٚT2rP"Ouaz˰Rׁzb9%~sQ"0t(F[Y=Vi|;%L9OHĘHw8G$[ōni  @dO iI#P,4EnFT6WRhG b<m5) |K0}s̆ٳs3űŘI,Vp GMZg d}M'9>\lb+č..& q# +֒ɿggT㗯%"s _gvDʯ+l)[3_h97,{eJ񰋠h H1-3J:RRu8'?O~1)ŀ~hω)STW=tEq;v%*Q25?x);ȱNgm2Iyê 2ݺLjEJ8䱮&nuf\K% -#4#hgCs\!WGp82С)t/ X 㕚o^P| 5ϲLcj*;HZoUq}3\!0@$gZaМ>JbwT)Ŏތ'D(n7ƗTB.J,4'0me}RYb]#R$cW x} \#J(Hz Uݣ8;6֐rlThLR[ 81Lhc qQ'0bS \CA:VڙKVK -6lIVZn6.Z#W+ֶqNqF[2<IM0ujHXPyQ$RdO99 zu$YhH;@ Rybo1ؘԄUdļq?l\ZtTKjRmW7@2syYQaN- ~"Y@x7A˸Eiz^tg&=vͨDB5#7Y˖2 |Ւ:W\ {B"2Jyٱ^׭ Fb,i1&VWU& !99ٟL?*77kB~atffOeҘM{Y@|?bzD"w)[9da>^h-yT$vL/ef %$lrbLgǑ̉A/%X}=#Cs~;wJjA0(2K5Ul-ßBzLr"O82zĽ-2uY:y‹8b{''D ǜ`^1Zu$'DjZ<7}PTX*cjFK儲47 jITX>V?SgmG{([ 0ƮF |RA+΄@o SϣV70j.|hCI=pڠQ#^g6uixHi%%%0B;.cE,;}14&d+iV0YC&l4Mk*,p@'\夣M!5pXe7+*'>Wt+s&6EZH\{aMY8岢$SD"JRQ#kY>׍=*prܲQOz~xL x1!Uj)sФEvclbU+_s賺Nכav uGΦ0tŨ̘Xݺb%3Aϴt's)YLKZPx@TTEF@\δ—qiꎩ\蠍يB0 '۲q 5q$0;:8pyY'rqЉE)AXdET-F]OaBsIhUX], J$I1SFCI XCH"aǩt̳ 呃DZ,sg[k>E;OJ[fA0ba\,)C *YjV%h{Ԫ}5U 5l=[Qfrgau'PCNؐayǜu?vFS9KuU ؉ZW GSTHX=E ,0(\ٜACb)rY>FplUݚ[4糪ZZ(O=.0,>Wl*:i*kM{=|*y2 mH-N%J6a9²*2XfFWE&̌- A"' hVZʆ2.V832+y^ A+%QLkrqy .G2 x~ae, .m'4S2CwZ|)KT|7Ct.9F'9n(^E 3Gw=1sNcT7l̜n8VI |e1sU:!j}e ue@4dP(1s㍒$6ʚYo7k?-t+P%ldϊTow<20${l9=㲂|:$̏--o9d` 'm,XxDM7|aȼDtɿty)9#|)i I -$"fB>ZVB0@7Ӏ3H)(7R'QڢWuhi'?C21>^ i?$(9u=9(QAV|%RO,tF:ey+TTh`h7M ]ݪiSҧBE (gwKeJ:<> nc<3:E&Lbno釀3A M`CՉoI( If͸:xXNY^05va݋$/ 9B\R q ‡>t(ߺ;6`'$"o$_v誮:өI"3zCTt?-ui&$U^D+L<;*%:9HH숲ɭaޚemK.~{UEHv&db<}(tc1I.fmn6 ?gKC}XW2r↛C!rb"Kԉav:ӕ:{%6'7Ap 0Whl ` VAɇ\"ҠO[ǢF&ܠ7!9*"x79KRUL[洐E1G- uD妘tVu׵+'F.>J0P cX=ar eF C"7^˅\zon>Iaq-vիzr=DZ+agÑb׈Yr:@K% C5gwGz>sJY:2Lt!xިn 05κƝ['Yiup˩R\Pq=!k*18Ke”{xtf)J%J UkUy_%vP,Ǥ)l&n oJ#8+I2WWu1 <ǣ\P[^x$ JSiciˤ#O]"?o`&6Xy}fNXRj1'Cun:# BeY'cdeBwC8a1̖> GF=,\͸^x=F=s!XFZVg\hR! L a?I|.&c &Yvb`J4ff$ u=b24̀(tSC{zQpu`/lMgGO4RvsD}EYHY`lHj;yAglZNxšExGffyVlV%F ܉Z6G2o4*T č>L$N[ĚVcK>6JmϔbŤ8?^9=̴5.0kPF*WQÖTc5EN CYCW86\NJ˲4 PmGJHpu t_%* 5CzڧMilq ]X7݄u&|Z0o:M21{,"$qd;?1MbԢ6rH7z N> ԕV'g"h 6YLe1 ̣Ё9w`YF,uF9>:޻EEM] W  ̨ܵJȕclP>tYEƝ|YwΧ_ko_}ڐ|ם ~ _%LwՍ^/__|yx{3s[?[s ~wwk/zނ_߯F)rTD/T¯w "=n-D޾ru8Y3yŕ_/ӟ+?_]tg.pw&|qG85w팦`&FzrkO/W.3y99 S8az5=37n]Fv+|W9|r)5MiUMf_ɍ'O=>غr"<ǧ5αS狻w{O7\{+ɝ7?gl'RnO|v᫣/yw~/_j]M_ߘ&A/޽ܽ9k3S= gWMW7=^>`(&[ōρ?>01 @C]2W+?O?mP(0RyYB[^~&WyCOw4 s'y|huUk;kɵ++O@X|^&+/+~,WBU]82_@2W]adpw;Ss__{8GFk.7nO%H?i5u06{mrዡaZML??~9}~/*߬<>.>" p%߹0Yᄒ6mÁ ?Nׯ\V9c4M]z}qڻrm㛿]Y{j <ͳ'0 شW>n-^#|9L7yI3x|2޹w/i=PBHfߠO\¶L}u4+#s 0x&WWVn\-M5|;u?~˸g^{zkE:[2=m׬?1jGmwx}^gp'z| Ђ^`@iB8ͳtJOI%&)itҾΗW4ujw_cEE8PܗwOn7h)$t1ӡ+|x͋p|u@!z4O>w7˿YB8_ո;q|wx|_Ds ;{n6껗W^ܔ]7Kn\V47qVu+ÿ??Gc{?گ?xZU9au`A߆Ao>r+~9[yx=q_qojdg ǽ+Js{ @/N^L\}}݅ s@J ;~ hK`c&2)WNo;gdGƅvx峛_\I??F,#|rhs@Z! #t;ݜ%OM#^jQy~tハ=x<W=rC`xY9 6OR87O_ojذK8 {_}Gz2OSWϧ__ބ\>1YS?5cD&_j]Į0;Wy-@* [!Vnt/ +”7ׄNM5L^4P7R hW!D7k+-njGVl͵SW̙tBXtA|dF{ +p_=+>~6-عz22MLZC~u9Vo7qӚjkX\9R $8 ”*gg}e󲦪M~mM{Ȅ]r`Rl]$'9c|8c( r4h߽~>]"u^bٛǷ;Ύsa6=~ f5zB ^F~ ;ۻ}k瑄o܏&W1AhOLϓkO_Fݷkb?Z14a8-_j)lڗ+D#:]l6l>4>~gtWS}B"rDyeGl3<ntQ޳[הxؼ%V>[98 }OoA9Kq<"ZJм>մV D&ȿr΀>_9fhSpOCo4͝CCizKyɿ`Zta LgFv: erm]o~E=:ܜ%&7:yxV`  -Do"Gׯx'o7>_\ƽ{,v,ݹd;H7hsRy؅S5كuBn?j&o:\W1CVM-nVxoªBI~ozCr >|6?`u;rю:.[9K/,=v5`R͞9eCq2F^o3] t5,\O02c23kcƊ?{,l]V}rVΑoa+_?GXM{luuԚNon]/F"z_tj3&it,\*oԹRd$9gO?C~u2Qp4!|sq{WW`=] ѫO#JX `Ik‚RcoV-FvLȄ=Rg?ON]`}޽zP}FiZ6IևQϟO_*zګ_wUۉPOʵ_&k<䛑jb}%o$;af*06pF>zA&KG>\)kezftoA_^4bΞہꬁag5rP+-?k'yuyf>?c3?~%Wia9?%/^+?l1n%~0ω5q=?33?D_h{YVGpF@YIJvv;w /_L.nϟ<'W׸mc? 8oWTcjAEys5|r0}﫤$:]uuy.=<>| -oE X=xhܯtNSϋ%DMfM}? ]jڼoSp,W>mN+?DiCb״giAp紧j~vJUsEnvV>U2Kuu _$.ue_7h V+Gdsuzkz-wYC0.~%~D͛CsTVH2inLr_V?ujd7!=ji \pmxy?"H^{:9CtK}5ѺKVn3}j~Ճ{oŁaUxq x/~xA&Bg7-wi5g|At #δk++;_̈z+Wia`H;vF851Fe_ω>_}zI3c;Su51y{tn,U;-mӟM :rae~\Y){[nVa޸R !?l6:F5!6/bXAX_`~|\ٙN0Wϧ?NYI^ /.?ޛʗ7+;&~Fg%d|S뾻r5ϻ'7&n6*~pke1H;r5dXaO_?N_ɓw07u.f(*{~O륷*n@vԒ j Хf"o{dr+uAYU~j+q_:+8! #H3jvB)3%Y 47_])5/k\8?;U@?2}\c>I.Oן{ݫ9 q*,uoUɵ_W`Ln@8z'P8b}(H]@!OkɵwWvƍ˓o{w7?XfO~=L;zuM@H@:,zCO@عL^Gw6`P3hS.>_o|×s$ky.Y;}~}EZ/q5q~>yw rm2l/H??ٌhyx<PAG&AjWx>G3Zf#Cכ5 _֮-m-Z?s~DAAZŢEI ke7 Ҭ!P!dDfue/Pnջg#rpْ7S,7 @nQ /8P ΄CoEpg} l{lUmaca |߮%J"찈bK`~_BA#ݣ-J}^F&Vvg`׾3WI}(pq(ZeF+O8fS!=Z=$idP^lPy0՘g اj],Cba#{?וxDž"3x#0t0{[9Fk,X*0+XR`_]=`Üҥ޶Ƿh_cb7{q.i6NNN{TeɧMS%> kϲ ".LӖƷ_Ϫh%fztm~o^Wn#|E "kimS!S+īAB^謻} 9=}·(?CݭG͜˻ )S:WMHs2A=ݟCL1CX"P?$vFC¶DZPJj!=ʖmAYKZ*)9 @yD))*LK ٝrKg21\*«>} 6Gy'ŘoxY@ei%2񛥢 씢#55ً>Q?߆ AD OXQ􂞰(b&TQ|¢%:.u'qGն%-F,@z=3bؖOWlsGB{ط;s )؝cK+]5/ҲC%MBdhKO{! s/ёėx#˦nh]vTTgnDR{CP  &_ߟImasUTUaO^ O!%fȠ86k|8A3\aTC2[`SPA8[[m;+8QX%l5,-YƖK0a>"j&hwI6[t9Ϯ~1 9 2o.c "-őK7LbLvuSKERL͢p#&4GFUluZi/Oj;Y>Sɹ~GA[Jp5M\`uAHyv6:N;98d`ћgam{.ZMu0}ۂxj;~0NP\/ae{1E<6=tl@%d‹Qs ݓك `q"䮡6&ʌ7CL[/aO_O8;-LL nw\}`E i}{b)7G.$ h#"ϠݜD~,G뚃X6hu1,}0JaʵczkH p/.B.@I2&<:*]o^#bFijooL:l&%ȓt~u1>g3ZݝɿHU{C+cJƾ AvAD- l'>pcu¬Mb^ gS $3k$K$[̻Aj)jVZʝoD>7"7Q =t쎎0yxT"P{Ĉz[%ۗQ(RQ_?̔rū_& QMEAM>VWW#kV }@B}s9 &ܹwC,)+7k7nT;WStouPx5.1eyXE)5$!{ !|}k! J^-,Whn7}{c P|"ag2=#1d2EpU`d &s~b˚5߱blͳm㛪{*0sy7Ķכna 1bHmMmv,4A#I+5f"ꯁ/-3.&D.leia,:Sݜ#j>olf/6U B2v7Rz4ޞ:>Gz/zi5)v/aY;2Jnq{C /4mFCRL编{qo"- +mk1 $m\K-m2l\d4xC|df|ӿ=H]h 僱Tļ\9teS߮Phm~39GbILxeNdv5@C*;`ZB/ ʑj s|QM1a?l!~eOLe ˌpʳ.|t;y7p*&(gXGXF(Cs)5c}iiQ-f{5qo{Hi({&Y+Qf7w4g3o| !2"_ytP˭KrY%%5eAH48gYUG91.joͰEuk yY9PנPRo̮~/(Y d̶%h?  'hU d iJc轣UCpk7cH8\Nz4WkDˆO?SbWQSX;R@uQWJٿjz~,N`N]J!#pZO:NJ ]E)3*/- {=,QKܚ׽];[AcKc}yln+Y^G&{JyuѲPG_G?9 G{3v?18\(:ẗ́#&n(dz6Bq|b›b™  +U!¾hk|bX7A_V|j7P0v.#1Xҏɥ 㙮e nrFj{n>iN]=kG;T/}Ł%CD,|DG1ߝ$)N4fj%|=^ni~ BP# )[cCҙTueAX+1ӲYX( b 7c2rGX-CcB%;r ؎8A])аUUR",)f3oVdE9d ȸ{rŚc-KQܥ T/qKiDRأx5@#xЇ)s+9vI<%rqjхbNw|]RWH c5zU Zh <` 'iw ]ȴ/X 0m\`_3R},= Ǎ؀smNMBQ"pr'ty"a{h_"?Re8n̂|?oY&r$2#$|_B~J5sm{0Eq++$i/3BגwYqLؒVT@. L;O!3Wa l?ǛoZi1drPA 4, |X"xu<<&tͼYŬh"vhWgW,N0p=;.tv+lfT'{Ibl}"80hagqr)\Ѯ4Lo=r?) lyl);S\ |gI >U0ц;UHIFȵe{S؀ŪDltٳOk:R ) 4I_H@B;qZ2sWsЊ?#W='k*.u5՛nu=_njSӌ>K pg2SWPa |W,>}dijjs.&z$ts,X)A|ʇ!̍HH:FІ^og2W+R<]wk_ j߲ 4B._\|ruR7h F#{)Ŕ$ޕ|ʟ Ę2~ Eyxʠc]36oȀu*ZW߯\,F1Mx.d`$AW>$nBBfܶzdd&~ =Q]b|3rA~Ψa$ Fz/W+(IcjUPNӬTem8 I&\ ̏tS*geL?ɫ1A`x*Z'2G&-? `iIi܁;81 X0,"Sp,c]n CTHH`u䫺 lctQ~l8pS@ X8Edq hX7:90_ ;N8XF!cKB!3m]GV2_]l'2܀8r/FkFypGyw&YeZ#p_3>}v͚i&_(C#`/k5Jq=oK R򶿁-I?(Rw & htJ`qwXR=+xocN ϐ'^xgNWn=A8!ez=DD OJ-Pg"@A  )4Dh(p؉gX9?vO57XtbRMZdy5T#v`ڒˠH0) LX>"BF؁|W\DQ7T\nsJ<5\tgxs]EL&' v^́G6iAL bcg4s|OrXb 3%syS ]KoOS% }&ExGo^ǽ)9W S>a҇$_V{My;IT 2q? h2_K[vӗ^ Hk֛th ^W Ri9^FU<)Dp|Y5IzjaAc?TCCa#Gb|:fW7S=[S[+ډظ6 ~ ҾHc˱$;SytMwY1꿚Fg>M1^$vAü]J>v>A4PX9bb~^JcI溗\9~7) q~5a)=I lG]Viv7 RJ(<)fɸKb 4MsË 9?~o|v>LEI6S*>ӭđQH5#1$>ߤ7O4lЍGbx9x.P7$1{݋Y@uOy*QLBZޟg)Qn)^0ٴ$6"&LJݱA5r'22_ɫI"sk)ڹ ug r D_.b9nƈ"JO%%GDm? b¾epH.sh+nINNӥtCS99$%Q!7|jyiL`w[ msaCm`\)JKi?Ip%.EbW*d̨v\ MHRѨͳ;j5mcV7~<;n w4=7ְ _pwځ"h=1Br`2m<#4qymkPo/w0"~o7\Qa #[d=e# $&[l S 8aC .$ ˜K'R&6 H}z(2Ē H!y*h-:dI$ i0D~uitJp! W=9##Jvxi$?@{v^l{ݨPw!νz0$au6R>Å $(z,mؒ/(N$-\9+Wf+Jvs1 ZմTrˇLU bpQd'2H%:N>'aG9ƂeG|lp: u`o-` BB0.i>k%IpYCWȅ.\Jk|Q^gUctZ<=ѭ1,0vs7C'VIX;"g7Lb+§O.%0G 2-LK$"  ۥx,`CJ1 `Joo~sU .T(C&NZYDpΫaop_ aA8ܛ /)Oo3lF4$O'4In=f֩k:Oܾsl}+ 5l0G;-3ƻ6"?w=4,SMj&F4OO2OXSFiD  #^ SCBEs`ZJ{=(2q} FC| zφ|*ݯ^2BnIBs>UZZ:`I.TKЫYC<6=>Z0IMv2iP%$!ojTՅw FW7X^{F׌!l9X0̪i6d`$? |l.݈ ťQU^vAg5il8amT]ڙDwc0Ъ^i[rRQq|b^E '^VL}px3e$ R;rm)fF.Ze|k$}(e inCq_aVSZSj0 !v d>yE]C[HA{aW<Ց*5a=Q"ݭ#rU3 `. 痵TIw2*/xXgWjקP!*|Zr-,5Mjo[ٽ _]g MP8NbRTr(-ɐ={WBH z;/fr(0>Ue"m )[_cW- ~d yTgnCL&%G#VRaP #K}:NzLZFI<=p[7 9:~icEzW[Y3r'+ c9NnGƝ݋tykS@d:5BĎlЦ<tHxs18xf.Ɯԃ#BAAgu  B,HTH+%Ѳ@ A[^ t*_M3p}YsRtĠ6P8< H bww["#$pWy:>$i[ULlt PTYaQR9?3ޚ ?S?;tWI8L6RenN<Ma!L7 ZlBOxj.A-#fКxLxPYȿ۾q#7P VMԃG_gA2 $F5۱؃tD:)ΞjLIVtIydDl>F}EKfM0%Q6zufS3+![c P#L7ZS( f<'92_ >H ~rI*/HxDi&Iy #( )d!E ]0Hh.#60=1@JIwI_9^96 '+h}I_! g/oLȕ-ھ@ҡ۠CyG~s/QJ}y*=7e0kVr8zHyO+\27]PVj^ r{p}U4W01!)>xӌK2*^dSzrU<rFv8Xґ0TdeՑؘAD^Jfn@p<$2߳ҹ @БFEJ$Ay%Y/iXt&W0fa‚ dOl1#EकR=0(]I!#ߣμ|,dҧ/#ڒpo^Ѩ.;fd4 -~8!5pE֦ k#F~/dv솀}5/ԃyFB伄*%(ۗxc:EV&/zfL3f c9L.}ёgXR$Zn0H9."o;uGSUG GaM߂Gɐ[i'?|i0 -Vno晶j{,LA'"AKtXT&7F.sO X 1g굦az;M t_m=R XڜԴO*M㋊8Tdf;4Ec;_N…>KxRyKnY>=ahHhB 7/OJ5°~Dȏ|\dyԛ$IW^N&IobG3>0УvzOc"§)RG6vfvgv,5O` q*IO6#U]-rL,!Vk/j6!7m$)FFgi*\4FiP 5#̸Z"3_TF$Q$vVꇿ+$[dDJHd+qP30 kUo +9E-8ڗ2?%|U-ɮօKC٥t ]w>̕2XĶ?,C9Dv?ȟG+D֦ k݃ vEly^n1χa5pp'f{|TBri$]G̵pž3V;pN8N''# { TU|)=,0'h"Cl[{`KW;`2ZũX;A _R C"84 ~9Fpm dEO+;T+ R\^\0/O \ы r]e["5HdZE 3 f.GifL4 8H80ke:^qKw/kA:n1UgZ\:GS1n]Tu:r&Bh+?Jt)5w)Hu%~xV=[ {V0[LZd,@鑍-PX3/U $럜u4GV`DiItpAňB1eD{NhaFτ|P՟S3<4h>t?/Iwd ^eڂpSZ-2E! ?@u~X[n.9(Rg)NR:ݏ7N䜔♐e[Sv1ަ }iIjukPm֑$N~fKNzB饴i {Ϟ2KNSXNO8-@݁^3/`N7h{N~y+Ej& 4i(z9B[i-:ssqMnῚĦmMdXC];]F R?@|U*ŰX!02U4ZvѫR\B ac^?mx0}v9Y0s> ݿɤn}wBH/@z!;0k< {1xZ۟Y-ã?+:M+6vIėF8:I3;%0*eT:4~Lj'vV<kf ^ r\+4x'vI0? Γ+U{x9?N+!+`[Ɇ, rM8O} BO>dO{5jh4q9sD|7 p+MX1l /̌t.hZVkPJQoD-u!{ze?knOi\|j(*?ru Osvט}v XZ9fms .p#gۜp&fn*/"^ZaI;B5qmM^XkSSLȧ킞qBo{{Tr;\ UK?=0mq`҃pCYh!Bj{len2gbzlx |Ze{ݕD ңjAӋƓ҂KtV *ɛ Ή(4%>"Lנ㲆e}JoOp&wqnp܆%B7!܈ ( ~B% T{哮NI_=DmwsTF{&pFN:JMJ̝ۡ%ZQlqu+'xTS=8cq"oz܊OPHiy~D^+ *"rlWKմa9]+‹a }Y]?6u؀:~$fͨfoGC[r3Rx 拏%[JˤoJV&d%/b",vA\[MPZ.7fbIP41 8THƥP-U .@K{ߩC@Up.{KSP cÅqvw_-FŒF@dfh _ds%%NSxasg{/ǁLo]Tjd2k0=VaZQcM}G>$eypvL?BqAJgX q+REAZJ BVeraI%>8$?n ~7|IaNW<]]{$AoU .N1<딎SNͻ7gfN汵@>ڴWGsie d6LjȊ?TUl2_櫭y4=މ"^t?+gIrPcs{#ѠhKr/a;B7[zD)aGqU HL+1.aMCkAaہu$-}æEoȣ"԰N!>ŭ^$m\a#߮(r{xX2v^'/g>M dm>ѫҎТ)@}[ J??W)9@K(B ;NMGHƳTdV ]c[|Csܿ"ewɽ<8 ${-AwtO % "t@8Fǡ|tB 'Y?MEc-k[]".7%n{R#[s,SE Wg"~Q3Apgǧ7b4i`P3Yc48~d"q餂YWdh-MDVh^SÅh#fdJڅlD>_ia@*qWcM'Jd1%3FP,|qtJXgQ$%K(U](-j9<ۣ}d:<%t^ٍq56IR&<41ŰD-O$jr6i:3aPHC d-̏>Nx{D@g!"B2bV!"c:SCLLc1T3!+;]u z0G rCʎօiiyvU94f$+@sB )b s_&ZGsUmJqMʼ|7nt!̷JrR-wVR!5W NaB2WĐFtVGSS.-%u9O:t]"m.*AUb)Mh~l۳CdY"84ԧCf3 {2t[EY*'M/3 CfdTS%#_Lqª qɅ3(TP<GdQi,W3t+{cq7Y7Gb$r/?I$rJYݯs63. :rӰUEo౯NzЛ kti no72oLwE3nN*)@Y }Jh)-:'$n/;2!0В>bAIC\h~y؛/\bWWoM؟w.xPx\ 2#8G#%\zƸȢK~3CO ^ I~"l?d!XBk@bZ3tK5??ᓭ+Ձ G+"3 :#<$~q,67nmrJ|iフIi)s4w%Egw]6PXҏPB_$'EaESSGMh(I!?fF-"iˀ϶O.6 >a "`$ l b䊶~R9DvhJq+5๳FC5ܠbɈ->@z^qIC=!KY5]ת` a+IϷG_i1543`_qY.%:U֩aaE<̷XU7NmsGw/8FNx #$nK+f-BI[=DK1WsmɬxVdHkP#)} yT͔,3BdrՅ͐DH]W9´mtꇮf5:7uGifj6EZBOz?+&K b;KOXngyQ1v5Gt0՜M +.ݘ(^UٝFN %ȓމ]'Imly M(ƺYG_'6d"1"Jơ*}5+ӹ1Pߎ ;a/WrJQYWL;$tO/܍*;}~0aޣaQFenKX0y)F3;ZHC}횚w܍kɃ_'si0ѭ%Wf-c½ -;#~ל(na10٢2Bg13[ZGM8_g Y>LP4bmL+eDXq 3mUJӏ5n]4a"߹-5Yc8s1#iޱHp[Vm֒fKN7FLDBrѿt 21ri\#d|*'9ӗ𕡫-EvVePFfhii}4~0. F#ewDXF6&lNy%̑j23!DiN#PI*ZA-:d5Ƌuaj~O{{(ySP0whahـh?H4| eog? BP /ʐQ|B#b\ zo~u4@|XYЗA͊}Kn[ P]Lل'4=PGot-OzBG '{eTtW=+auԐ&raG.;\X%l3=wﺈs#.V-+,YŔ_ͼz&ݑ6~Gk;EM~߻4(ѾBAR ;YQ6_B/g#cSXVJJx 81}8PvYTar= ځI±#U+lݓ>IMXv#֊AEX:`(@Y9rd> ? 6W8PQ**DtpjEN;3 I&4ЛJ aխ6ֽ,M݉1NNuRI޾V5#kͳjj#qvD)#ђ t.Nt>!3]B2P Wvat aݧdUIB6z(+8ZVzGFVDٜ#T a (c`,XE\ rhxt2mN_{mΜPS( -rK;Dua˕L?t;$8n1XzEcKqc5fZ6=**Yݑ:4.MII1 -xe̡^DJ#  Jя~.GAfQe b'屛a ƈ3PL!g )/C 0g͟L<]ÃuSu6+WJ#:k&qXkHu!X{_  i+Ӑ`S .TdrBBZzF)p8 "] atSkS?GBD"JrztzO7K 3 Pܑe@u?d j(< vSFd}e_O!ë?sp AZЗ͢(:XQ(( aT:[E9Gg#kߚ+lka0'n\SaTQ3 mah'Ix,%1 YL [=eAD־*(hp1TWKW19|х"vd}&QfK9oJ= ?* N@ 4c?%FܩTgȋA/zQwkՐ8R)VX YSA=[?[j!rޱ^{*[֓$3pVtkVl$%~[E$6dZc؆?QPg1T|HΔB~JEumחzGϵ 4H!PyivM/[ t#ξE}u9uL/SJP;U-O>W'+DK)4z%cf]_?m[I$TgN}Ac-tћ=뷍ݣV&\$ӝ[ +Ate, h0/ n?fWj\ęQ$vE3 N挨 Hq%}Y`6hMSѫ4Eލߐ*4HN'Ct7wsCK)|?/U'kgIO[KѰ?) 2dx47JipG .ؽL9,|-hqSAG=^6F4dBgGmfk2o44;_Gf)NEwITwJ4.>* )mß4`gxWN51z,m3oPX-7hlE$v06_6[vyasa3C'N==pp#c/n DxcՂD7XoytZ7=oh9so*)| 0Wٶpf$Z3{^ݺq Ј94,vHc ڥl(z|fbE]&yL7 cʯ]bڀ*͡! >da:f()$ŏhQKQmRҪ5>uՈ{ιGT?:a+wA#վ:v\Whyhth`h/ j -HEIG(g A+57H}kp~wӃndY}v-ݫhPLRg /ۿKcDޮR9/B8SǾ\Tt@^y_b;:E(.R(00HAy X$?A+1:8pPi7hۤ}Fgp.#ٮ˧B`7: у AaJfN*v^nOܚѾ-lB@)_$!ruH6 y vv?XEI@ DijG$ZZQXJ5|T jl< [$LRaD)²:`,S3oIG]/n}lUF#"|?> G,PP+ȡ~Md]@}:G7pSŪ'ts; DTwZ@xoonH?`c/^Lr %(AEjS]JcAN 6: 6=tԉY^lG3weݳ (89))Y~0dj1-#{*Zl^>$WbȦ4M+?{ޓ!a}Dqnc^cA98:_.̴ ϖzsԱuLiVI gޥ9T-Wi9g+_KNϸ )QBKQi=8 K݋! Z9$Omy٩V*a\KA|DyVKZ6I%X P=ߜ"]:^|T!gADڐH꡻Ɔ=ޠq.:˃}Y!H2o9|"|1MO&ü__놐4[='аlv}w:ר(Usi:%J4Qz>H ;AO:SRIl| qzzUCHA&Io%Q%w",Z8cDK,̷8]'!X!R`k8V5{NB(6x_6ꈹ=^ԎT/u19eM‘nV4t.0 YCE0[ՉGOMBhKTT5]ڮB3Lz%fwt»^c&R qҎ=at+rLŊ^@Iy ^9 H=ADF&_״Ssഎ^Yߡ o5؍?Nm2q 52Nd`)d4hJyGPLM%` xVGYx܌~__'Fl: >xDuuta?h)D'"/1rB,0'/ZbgaK!>4M,6X|6Vlt.'绝e?neBJ 4oAX!`JES%JX 5\1(_}4tW:>C$Vqun$h$O-*X?I(9@c =kdlI]A!Fm`ԺZ fyۜ-4 ^LfX ǶER,Y7fxW̓?: X%UDapDMzl}WPNЫ "b9oA 5|Z՘[-t{j &|x >nfu&fuu HRDҌsm;Q*}N3Ü&F}Lt!Vw;ȪI^h^$_ pR^\2u5sޜr1"iqzk}o]" OۣLGgɔ341aZA\j3[ʊkX^u44ٝG6Lw1v}U}wWF}{N Lo]>m_9Jg]ʦÇN&'l薘-r|S~xH\N yp&(e.NE6J\R~+M+6u؜B_=sBnFߗy-fw O= %$qs0|pn,gbջݴ}'Brލk ib<_dnEC8oPi츏ΙDX:*6HSnUjJ0AСDbo|4 esbxDt\ =eZg2^"` #wC0m~*~̈́ Ӱ&݆l-(kE3sZ}j0[/:ûTalJwdDl@x1wwb_S|NYq`਒"d g3 )rDh eyb/))'lW7jPTPxA#q]?UJ mIŘ1Gonh)jrz)8#=]"0rh~7@E,J;OAnι{Bmq;9[)A_1,yJn˸( qϠ45U\Q4-TbXU쏻h|RKоΆ!8:=QJ2O4 .h;+n{'ڧT<{xW:M)ki:^m^z8!gA5G_^ű Kfڽ?_bg$`u&Kq;·-a?m7N"GqF}e|{=5dz_{^wv\S.Ee{b~ wj?5Ho[b}:eBȏxXc=R^|sҝW,AM},g71t郋 PE0YӋ_ŃZZV?EJ+V?Z݁X|Y9~3NpJ3!žRݲUs H{2+%G;[Qo?~< jq,}+Q0ߪ w $,|& @k:]J13 4 դf >`/Gts9+5*ZنV'WNK=xls7ua -g_xE)\^/bɰKE8۩4MR0-GijOqJJr>sjCuM{ipvhQک -Ul7Tgز2_*uW7么R39oQ͛b|pf>3cLŴV -\gn[&}~]a\#xdOaIKD1)ޭG1$@꙲Ti.;,jLhv>n;JjU:<7Ӓ?i"oK9/{xl\QG_  aN-cJb )J|Of%Wbt-& ,A]$h-H@$=JZf/Ӎo ߽:h%|ipOa2qBsGr1BOp':fp<ӧBQAgeQݔMAmxb#j$0:2rxd[1@H*z>\n4WX݈|l ]=|7Ђ Nj '@BMl4rhF`\ߢT4tlĶk?YEhKMKsunҖi"^&}O/PY|H0emDd^m׶׎jkkVCDQO[DR^l$s] Km.7.Ѭ|+,.gNj!H= Ta,fx̭s,YQƃZ9ODQDQ Zi18qC7YBpqhf{oxbO:P?-pebp;S[\hM8) 4Uo4UVSSTJZџ8qL116V_W];s9)Y>Sb3+i`[:7EeFw8-*Inw7IVTpmavGX ב{߮4$0lVDW$$QR%SAM=ƍ3";}?[{&6nVL{W *fϪf8ל&!fl+ ӳeKƨnSmYu9y;p 8nZ&`fvAs\}gǑPuq j!C Qu(nF"+8lY%J@ =Q#o<;$zc<J$3-&BG_fr Jr@jn_[(0vG:>`Hhqw.WZhc3>H8/zJۇpɗdK.ݱ zJsI쀻ȹel")vE8AI33u Mݳ腼./vcq]5Եݢ^gj}MjhMyV +LëhV:(nkNd,Bu6:S4)~AԑᄡZU3P'جqB¢SAl"8q_ڡVV %veXM_[O]Zxsjhբrf'WLs\\- S* ܚf{&fra1ģ}P[g}KC3ed_z}/YqQX'7x< blʎ0ElQ_'P n:5> 4䜊2e]~`n #I|!L|Yۏ8QJGL>2# yE%βd_ =YqJis5|+4k3Z |^sWIJEmOaF΢ZҘPsr"#V޾й*B: wT'#8_Si8t|:ЅѨ^\zmba[S߿N ^,~l_ 0>P>&Iíx㵍t,okSnJ'&~loy1jji%@W(` ,lzl%/ ?j=Mo.N*T& qŷ"1P%z:n.j2Q8)F<1H&r1X =ӡm3-ܬqx6O3oL&Nh9d0n3 nI=xp#+ąg'z, D>:Y^R4G/5bٴӲriا<+R# BP%ֲŴ5h1Թm4tH 2-c)4E7&H[I]F۷$Ŗ,uOO}xJWfrF_ɜҕő+'CD*KS/:#vJY;ɻ)խ?u--52?~[WSm>wɷ?7لv!7SR1C_c<-t&`^BŸ53tRe4Sj^]D MK{O5L(s TH.]H~oB⢟}jAT=7D͎w6Q~@2EXƏvmnܘl ޢ'oe'+OO;I`JYbFl$| s卿5C]{Y>$[?~PLDAtr}+2_@q˂KڣWg3Gc?'^̑p.&wbv6)r;RB`5Swor":w #I>7Фk}ft){:,hP?~\"+u%ӔB5^b 3M'529WCr Klq*eɄ")UcY=r4TDy2^*M"O s zlo3}ܳGVKϾ85|qj%0hu$}ZYݾ=Ǡ3M?~p[km[{E`0:ax<1kmж}_ê8uz]mDts##K{K0df+ŧSX't2;zyuKjpgoX!M;Cqx]zgxiWڎY ?,cZgiYtٸ[Ug[NG?D_uŴ}Lls< xM_EluYb}͚oH82oH˦6u2\m`Ц7̉ny7fPar*̾ o8yBz>@Ůq '6?eѣfbh#!1yFOۋ## <Iހft, wmd QQ%HQ)uVS`B0zҺv5GC f *lM;\j_h23L$F!վr`aՏվu܈qa|o:]a;'XXN6Q/i ^:J=vY={Vk<v0RmbUdJSұZSb jܳ_xr9:} 9ڱtxB=>w?׉v0$^XuP jK?4I@M"($ }{}OλW;S'ש].q}9$[E¦>pߜPtA\<xm\;JXKJRaL}z:b3t2bY(޿S^nw`u[\Ya,h%'V4<-lswX@xك+bWXLeLa /Č~!R!;.yf<;1Zw!8F'-b{XkcHַ`i]b9xjTrmn~[s0#hF&[n|HOP\xj$V7mP& %.B2vHSCkSH ]!R@D~ ɥ͍z;P|'5|/!p@>8勖4F-sx()Mvf>tZ4Dk})Uó1yUԔVnF$23D,@X#|TY3@ п>R{e?-ss:yBx)<1ɟCh݌d.kC8(dНvH gL}m}5~ 1u{KRA $ǎv17bM=BD%a ϕ+:Fz@3% iw"^88IQZ`N 66YWw hf԰6Y+^>&3dgwW j.Lk/O.+wRhm) 6#kB(bM[C_S1!\yIfb; aPz("<|qta> NߞɝXdo_@(XCIɈ1D/6]`f́DGDo? $/Nn_VlM ކyڕ{z4mGlP}GLU=.4&h$%~>>b9\83v\[a*q̎KX\fHv0`[ݥ "nLSLK1V8rA^Jr'H}zu襕4~Ckbz9v}@T{*{=\Kơ7$&DRr& Pi9ȒbZ|kZ[v!zi%v$WWtg}J.Yo=>#Yj4Cދ\^ln.΁S洒  XBG.(7Zm+ϯ> Uٿ*cᛇ*zc~AҲ/},)AZBGzJw-[.K;蝵I<o:<-6Xa720Ic$%d}0u:5RГ3lqD8U)gS-)>͚IPc (Lr)s'戮\vLbYmdZP-XZY.xq{L| _*e+'>w|'5r9b\*/LДG0,Z>q}=N6UܱM ^RHk˦hu&9B6'`v赹o{>l~ ZD3[NNl::"zI p!]k X{ީ˚_%PsM9ཾ=<((K5 7`D[b BMQPPS9Lɳ/hIgr,)h|f5c/s3k, .[Tm&nZ{y#$krN[*)'>Kt 6 Յ`DOõQ收]Q77~)> pWfPoڂkOD=`BOVW9C81\]B?.z Jp VuRm"o[a ѿ !-* p6]]V9*I JZb[XscKs1^]ImJc ;LuP$o{u2kJ.S h80Qly`lP,{40 3 HՕ(S.c`Ug2=3]NJ#\~`r.UV?)Džߊ+W^]iYw-ף;~sC0' CyγJ_j\םУ*=CE[۟GF17oYW L7"xܧROҩqWb A{1`|$'(Oh m|XS!I't,J$j߲"h}Ϙ})sY.@5z9v+4|-C`\G@:"'MKAv{Td/n n8K'c=i̦ ]I̴/ xXrϐH?R6zx01r z$#)0l@SkI'.W$ؐ/D. zȭH~X5Tcg [u/_ápc3W16z/F 6z@& )`Zmy A63: 6FjG +(('B|#K /K}:B3l YiVnIi?AXdF*g'ttT$h^:G񯔌ofK_ g҆F++PGpg2ėgg0L{YK%̆ |J.W?-qⶔ`.#y887HSxw F(FHmo:-LnBCP{}6÷ۑ8|+xVdYt{>Ky|0>*dЮSEaW6G5NZAr.f]<3]:l s}NP>e{Nu'GD=W ;7;OqS:jb10?J"6_spo.z;)Tڧ-*W!C&K).x#ӫmʶM:-[c6#eBjQ  ~:~sku:yBɖo7,h鬝 9>T4ԛ$RZd}g@ 8<Q'>8$ttrxon FZH<B\%E_jL$+_ mF)>Ou `1 NYfHC_0A(\QP c OW{Ó̐67hJR_E! :^SQ`n y\i1''RU∟-]GoD`m3vzCѣg6]cl^oց9h8 ۴aSO=ZSFNӷlfaVuҎ~bjYQ`@Ĉ.nN{#1,z5c8hɞlXB39gGE|ԝL\ ep\RÏ\HW;%[xqpxX@5>QzZw6[̙s9N(w>x˃øm_ `^%zN]y%qq$lIZzH(g^44|&pRaa` drOߠ8W۪es킠E.r segm_ږFӄa@Q"D\Bbh4Pae|\2]]]]u]U>ا̔+ /<NYk/ߦ¶H<2'_0zM ]K4jh"W&b⥶JĊ-W/"836**\wi|Tl2ph}%l[!恫p~EQH7dHahb!QOxY/?BSBмPKz;́XĠ&Xgٖ ؋{~ hUK&^Jp9dxf(mrcqZڸ0e&  >ֵeZGAJ 9(P Afx.8x\@}Ame F},ܹ=$mӈ[]̊hbpRn {؆6AZ<`7!3^d]~BGktnr#zva:Y秘 =zI ^.ok i 3W] w@Flb8`eNr?whNBdXTp' /OvN鄰Tim}Knx<7Sy}pK۳J!8nC͵ivk`'Bb n:On%c‚vGޟi˳zs~>uz >d5qfFmAȼ㊇я搐_+!:ҜB# 82D|C;;Or{=~Ow7م,őŅ>Y1 &/ꃶBk1VͅF}ƛ'9!JG/ b_x3%/({p ȏTs5&Q 0# e \xٖ 3;,0rEF@_l"JHبtӲ 3 f^;S]B?u[ }L֥n0DMcKGmA%tgHQFc0kX "  .ۿ"#ACũNNt3Qdnbq&ְQ&|Ц(W@5ft'E(En J,/ϱ=엉2NRm  Lt8-DqFߕ~ ~{ЈVu8~ctKdA,0$S$$:5 Lƥ)'#bW5FqJ )A]Ab|6,h eq`Sm?P!7k˅NA=@$#srQ546K|sfmWKKO:Q?xe{}bݬ1xyTA0O ?v3Tq @ӳ, F3tF~BX}tD!]PgOIx-y$/ay- 3kB 7o51CM7{2¿qFP.\7n+`n( tB#5ЙgIP `Q*dWL w&S߹ kОXun1:ur:ΠO7C4XtIJjM$}D&BCDVCBÆD㜳"r$\dta~dK.Uv3ȣi}ʍ}&6}9 q7 u5 *Alݯ>q͢61Z,J~#a7*qNor&(79K8PP<:{t7>~5q°]j ;c y1X 3PJIQjVii## TZ#RfҪe K#gGu(=b%|8E<%i#!5'R7. (誗9x T>hh'+~ QtyH6m;i0w70Ljs$(%LTݘN26~i<>d\/aReqb"\)b:ݻ*Prϐ+hXQ#&oXΦ1O;aY%)*)'yS# 8C.ğd)ckA4)|=[|gg:Lg+$}})ǟ={X`FR1gȀBLmW61l/ ?͸W&q왌rJ6,(b&[)?!L̹)Ètl>zͣ$y(f㺜bizu<\*8W St6"0B<ؒFt$9#*VJŶcX pf6\* #\}o{sE+9 ['8/OLjA?? L2ԉ7i- -G8J„B!yΌ,z;QGH*#֕Gc aT9VFtxbw@\Xɴ○V 6΋SV!0r|,㾝UĹ gz};2\?dCt+{+RAAIs.G1?ͤ4W4R5%puP4,%] X] f;7L*̪X&oV-QwN[eɽV0EA9)2%A~W*QqjoCLGd w?u"ӆjyU,^SWl,ղ{CO[M'Լc)m -HMC.]~s\W.G#?M* Bj&r~H\CyRW"K@EcKWɬDurHt1*<\!%BKKc!6q^+뺜,D.ZIBś2"XLH0CTqtnxE/Rr_͂ o$t舦uu r^)ly L:a7z3bI/L\~IYT(8Љ-N&#0|a XcG+;"8 YkD CtyOrl|\U30ʖ(ebIgF"uH Ԃ>)UhbՔ=u=!VZR~%65̶|]&L5h1qWs45Yv bs xLOFh@#x'Ơ/&y^uti$w͋eT5fe Xݔ8 {oS)wP*$a683U&*9;Xi?+,s5"bRX8A\j^#'uGD/rR,ٌQnj#hTI8c=*VrIiʡXy? Wޟ˪sEc1J4:.Ö;{R_K"DO/R'3)}#3}vMgv6/9CPm;SfQMO7W~b؃V f | xo.ངZCUB]wC ,f=O6yZ'ϯd*IU?^vϻrۛet*1D2i`b4hՐYv5'DywN}г/3|+ dt"lƒ}QYQE]\7?p+/yy$!̦}SsF.xy;4ޛoeMR [??ۛ4p>4 k1!m KҢc0QuMQɖ ^-;THgԛ~B/] \tO2Ϟc&,Q>\"|ivL儦޿ДuwR%(8 3׺.rXA4q98%h;TXd2H ݳ=m|S1Վ"OIoAGjd?}qobdaRv͚hArMS*T9ݙ.sIL 0uUp˅BKC3ťol]k,PLnq˼ ]& #m2]s(LD1MkTKCیz6-Ƴ=/1:I* ~Qx+}'LnRQHHՕ䈹y8nK| 1 G\,9mො {5A$?A̧1qc)m̆1&!;Y;[czE&gG=pfZ:}PJ6'm7ƬUȖvMբ xi_8IZFub_Nw;̭X cwp/1BShd7b[;d2EH'0yEHú^ZA> ߬Qf|io!*Lh$oƜ']WJOp6r%"Lz 8eD:uAal9V;L,m6ͩiWwRK.&x.7O7wѣ=azrAS۸x"?4N13LAƛMvaXHK;j?miHwӭk$JRR ;ZJa0va$T0lK_ 'Z^z[9\g8D87Wv9"zMQ޼ A.Q^3m|/ [Rpܸ ?-k 2ʝg) )N "/gZ)V2:蟎)0\J|>8hZ:rmfQPJWGK@?:jjEϝLڮŝq"$pjVj"Ov>{:obM~q؉.ש?%:/䥦v<ŚcF,UܛCfoNoR{࢈Z9]M r`$QZmaoea!r_ohPZD^MgQ-cjߔt8g2STQq9 v~ngB{]!&)LnrJvWi,q8`K3 N>hަ%){i85z3 ^=S7i <'M`f^QAc]Eg([Z}8)pFKoφ2xv IԊ&CU&:d6_ѧ}~HJ) `T%ˬz`U~-m,=@ų*&S!=yyl1}"C jl)WI"CT|BWu~9`}Vv̂ˇRA!VF9Įwxv9a ov%o\:|;o#9\`w@XFJ&ʋdZiru⌉ezJyeާ!R9 O--s2h.SQIUT1ꥂ*e7 o`XeոCϕ[EF KOlttYb9m03F7wah2ce'w?/)G +6oV@_i^=J}_c2Fط5dպ̜A7-99Ǵ8+gu6F'eR 5vՏ+8iBhNma8"qXwNGY^0QUN!k]kp%,o.ѮVh։e@q2xٿ/k?i)x- E~^^4nƢ]DLVn G)9t&kCdi*1EML*>:X#V5F\uuK6ʄ%T GB (6C~F `ge4,h][9Ĺm:4;zejܑk ƞ~BL!1쬏k%Mvm,b w1Lskfm="sC[d9-g>x' JpA =rtl#;/4<|{UМwȆ Wm'(e&LE+jYaRpP}V'#/ \ I }sAZH CkWi 9}4^0$~A7&س/Z33U~&[uL'5|ʥ1Spe86)['kų{48I^4 ;e&e0Ak{K"d5aGg?Tsr[<{y ij tnb<._yJȷ!93/T. 58<'tsb_>S/{+v K!ֻ[<1EO3e$cڛ1N`EXQw:ٵ05/_ 0,I^FSu+?x+׈q߿oR1lXVvL >Lbґq˜v{~Gyt@ ߗrG =;%+u(?IXw[zu(ȗyb:KP a#12Wް +ьVW{ms j&-XRghEmN.9:ZgI\f Cja\p{ZqNX6@sRR)LRyK*KX|Y2%7&C<ѯ߹EntZ~7W8E5(RǩVl??g ]W"a+¼,8ӈWEh+0^m4lkrhv9 ZL6A@e[&8óNigu F+:$-pшҹjwdm `̵V D\NӇoS]r6^Ed ܶKf:11hcD]&$Sz&++5Snr\N?An]q7o_>Ule=G ^^$" ߟ9M(z}hDov+ȬI)Cdc49wH* DuـgT<)d=GcT=Z7QuRbbA\xtNn>,fadQ49g{~!Q[x9RtHNqjcXۡ, G<܀2`SoЍqQ ~9C?le5(%B|Sȧbй~gfP/.!оuXȫHBt;v 6X&1S_oJy6FQ,B0`!/3-Mv cz<~vZ;AfIk~M/C'j}Y\aMɰZQȹ(['(7&Mp"Y}ki v{opsTTeNɛ^׿ ) +8W(ǍqXKɲa c `:ZI 1`w0qgdpGɦ$A]f[Fۯ Z""lLG87vfo?[D|HI\ !ȩ^?/]W Sn(.)FZޔyɩ#r{*R>jxKoG(gm %bb;t`oGD|FlצNl7w"$,-~h c1BU0ξZ3"nQ5J2H`ݻҜ&n|`z;x$gaic,ՋUF &;%LEP95R Na 1SKLj9BKta Fn49)BVt04[kP ×< Ö`9 o ,B'VOʸtE>@ (Qѐup>Y* f@>yYSe{6So N? G.|2r`BT닌츛pJ:t=}锍\q}XlyN\Nq<w"V<;j}S{iKǽ^@_Jș:L̟BI bw*=tnD7zeDUȌaZ&Fz*UN?̡j%!{KS{Gc(򅫥@;Q˩Ze]żeX4Mj}{a?h$5bU;h@zQ8̍u/4 }\$0 }+s: $%\G9f#PZIIP =K B.ֻW3Ԁ؊xO 3wg`{ 1I+U{IhjnB#=Di! w ~I EZg˺q+)Y/rāMݤnb(4نֻt '"m8{PU43zySHJ-S6W- U0KU^uszUQ8>͜_rV[Ekt";E&1ȓV `+ eh͠)3΅ŏn#,.Wx\y)&7GiSϞB`# :EJIF8*,X[rkRxP|xT=ѳ~{Āpyc05齉cIDCx9cTR1U>@-b^`ʣ)͂, `IMf{|0 !1۳fJ⶷ao.^Sb62)ӋTp$SU Yl+@/ԳLXq yLnv6Zk?6-ֱp9ÁW\E80%(#2WZ ry{D$!f@\7T@:EI))zPy⇪^%+;agO0[i$1y|B7xbpÐ޻:=x9806K>q)ycR/@rƉT _r!,Vu.]}z]'@3%޸JP80WIHR@|9 \ ܽJ 9A1vZlynwZ˻=t&ӀU{!n8mt^w;KIo&~N>=jIK@qԳ 5[_SO,2Yᑳ8K[@&\8/Gzpw1!.qcbn1MFlcM,h.aJKm rVY_t=b ?AM^qVl BM@!OH8hS20ɽfzQC.删wdhi,.ci஀>Ku'寀qD߆a D 98;9.GV/r8pr'{X^{>>ݦ;Ү-~#ܔH1EW 0NwO  N17 --]~*ETSo>-BGҹx>p)or0|=lԇǻ/M=cԀ)E4՝H9H$|TķmX?#@@ )Q" wy5WusyLb>qV@왚h (qVZ7!N+RsODVБO\65Pz2t) zMďy.<ߔ֤h7 7㿟=ފq%ᚁ3EW:QyF'3BC27WuI:NNn: C qmR`ʓpvpNQBOĐwxZ%sRH+M+J@n`N1x#h.DPָ]G'|ZCYU\sP+)mGxS4eRBKW[Xr-k\dI,hdcom%9cU<" .V՟;Po>YkYs(݅ l;q'T쓸 (f">S#=b{igX{Ow32pߜ~wqWYZ,~f3(nlqEc#$tRG5(e|޲OcmN`jR|A<2? ]B2mo"|˖E|AisT)S SS - sȸB^7w$_^~/7}tY4j;qbְ'PZbL#ۻG8Hyb16~}m9}غ6鑥n|TO{pN I&u;-3_"Golo6q _m2*yJ+`FVG3$T |;);"=O^aHE Dҕ Wսg\Zw)^ 5t:ųqE6#`1?2EΪQG۳Mn:ΎZ<8ut g,Oc}[T!nRcX¦*^So*tS gp'rx"&JFKV=v#D+ܶ^]^zWځdlwJzm ,_~xsY\#cD8I=xa2ɦu՘A. ޒhc }?\^/填PޭYwT RM#Z'|er (AΌ4] %oSX313-Y"K3~O']F@iWn(Oi"G.>Ԥ{3P79}i8ПY8K.M8VeyW4鏇)Sl!DcMD=oac1/}Jħ9=䢩_ Wңopuxv#KGj!JBէU+7OIGX@KL"? ;FLXlvr0t1߹ \(\ 4Bq qh|3z~a;:L|{鑅)c: @nSx"Ur0D5UJ:Uyi+|%.0Vզt'ld&S2#|w[Q̝vS'}v\uw43yƥh_-Ǹz Q:2y;Yo^3L zHZ QԮ0e,<.4c]I^dŷ(]aɿ%$eMJg Ql,MSL_K^4TE;> JW\HMRP%$Bݻ!S혺`V6Qݶ]px#W,$ic@fW&=rI2j,>܇$KP% ;;#_{٪c3 IMevOs 9b%^dnFTQ*dQmdě9IP1xj P[HomcgzTUgAWNWBRAmFd:1aٍϴ-(nU4Mnvח-7s =л?{#ߩiw奩Z:;4wQd}ΏYzۃim1{)o|#0,jNݡP~Qvǯa;++>X""JlRKʑGP̰Eg:JɖߏgޒX n å@+hOzN\XB@ʨH&& -ɫAks64">B$i[ѲL)ap[m8{n H+>}@K4 A`9d)tfV!=\8~l۝) $#Y:fYh9=\P`mj`K`cNs_Hm~:bwrd,i|>ƙcwZ=CXL*ޏl4>~eLzS{51t$wvӗ*F9w7n=sSHTpsF7QUh'W9 lQma&t;ViEF7$첯xKx Uskht<Ǥ#|ŏG~p6s cdg!afK'.A^ o2TU׊c#oV!tnm4;R< ~Hߧx gqxh`NyVL7},߫!^l&8#0޵~EwV{̢ǐ_.DI7yי)ƹKZmh>I^o~՟Ofr?B+EoxY$y箃"C(;D*eugQL:N 'L`ܻGUW.|lW8g]q@tHR^tS fiF&>dhwKyZr4&eNuW@bΜߊg?'3m '[ (e͔%9%SK.H3:R28 `Y߁I$H<4'qB7vOq 9Q&J^000L4;(/%ޚӦ,7e 3$Qzvv_R!w`n*Tze{4xܿOjIR[R6՗g/ bLRep~ldي(e:o̜#xay0 3MDzλ*moGaI6,b)NXBkjw*)Zfg̗4 PhHojT^uYSBO^iKSUcZ0.)#4YTxIT^ _@<k)Q8QzaٻU]"GJ4MsMq8SNv&g^8?F1;WkYkf'4OYk!{,ƨB51u# 0;ju1c0a[bK%B$g+-(aU s}m˄r-c6=^ӻW'Kjl~"jpo Ŵ&(b-.#t]â6r3('vie˥x(݋ vMdN,0ܢ%o+sm2d1b֒b橽g:b> .toss-ԫpܡHdg#ܧBXK3kzal&.K1\PTd8ho&gZӊc*(|(LKL"iT, $M>׹-Q eq#@(! *̮w*B2i 1o,#,ӱJw5^›v2l5#iqOV^jgcV~/f}3tT>HhYXoQ; wyAb):r\ITV/,sf_A$Ө xDZɭ6U;>\U|zsqZ3Y5UnD 40۽jonŽKNopL<ʟeZA"Iĭzc+06P6ɄOh"Rŗ~-eVoipj"ui"Mq=<ᏳG``iՀE7=L_|R`B:tz,X 3QFktX>̓-d3ܶsQ\. ؎*j)ej hUʍDH@=l=- {fF{e+*):do}˩"շkpA 9sx)|FN}H#_KbtGUB*U3'(#\_eD` 7\8_W0ERP\o & ׭CSn%U+M] 6z{oS xz1d:Ԙ3GZCH/=i$sгV#NdaHGo"LT=\xCQ#30sFT6:2 :nH (2nnpzX3f(8qN Hh>^Q5-ւm(.)(e6cGE y 5[f7l\ XE5$MolBQ|gONj;k8Ww]SJSTJSs&x!$t,(4,= TU*^B\ Fά5[EB<ܤF"~mP+q% 46' pSM]j1MInjSDNp(a' g!IbZLW5hV%:[<8lE=:O|^/R}[}\hr7pH@N0ћĶCݸT)? |x2aA+a2ڨSu=.Cj-;V-I\v<:-c%>YuY%p?A0md;aEU_vTqW_ZֽdAڧ]xT,E F .#edPFt'9ϢDfCr/gx_q>ӥWE .`"8ZÛFI?SK1bkE$֗pc{=KpftMj E)n(=ҷ$3{ ! #{vzdbo&8t"17È U{ͮ M8$fXыT<]_ ;Xɫ47%J[#5R2MšP=?#yoAҘ]T~JvIj0P@Â4?uɖ k2,@ʌKzxUԟ~_dW} Q)qѱ">>a&s%$R?Fot0|?֮l;m%ؾg|gCb0]ݒ!-1wUvv'FƜ>MLmJ忺M#J7ϕ#C1Li ˑB XEi)f=:rޝl&qTn8.O­c~Qv ۔off<l)ė 5G26/@sE DJ:]oq-=&F=XsAtfÐ+P E-%'Vt׏^򗞘>.'s.iFޫm WG3$il+C[Onm{]EwO+~bFNrQG)Y,XV1Y5"aيin$[Yzao. i8|Zq5bv:8FGm( n7Nqcmn<*кJpMӪgkx:.MÔeh_=!]CO-3]">QaRpPn2RqcFNȋc6_}N*сqs2j>x/:"jy&VWcx2O4z`:Ʊ=Z )MHf-Byѻ9뽇vYXMXaҳZ1;}G(_ :QMw';}ON W(z7^Ulu8J]Y$ ^]ᡃc\,STǵLj %~9 '<[-˭iG) x-]8듿V?$= >CEp. Y{+DžfS58w ibtӡ[ڏqZvfwc=2%|̶D -CC2UE& xٞkv?ɅF2kqjPR5ck1gm s0{? HC}zEq-mמ;0:7dQW9W]LO"67z0=R,:Y&W,?\~ B.}>gq/hyB9Zêt^mL./cE!T@DZP#Hm0ȴ=PI6E?o%6vݰlLܠ )>>0JxEfߛeًѧ]96'qudT+a;n+Frޓ=rQ$0EMG6kxrΠ{_4 @8nE/UmL5 q.ٰg$:Ar#ʀv!:96+܎L2l_{5`.W5NC~4WJä9dFΈ`\oVKY?7LMcGBgg H(N~@U T]gT}:yE‚DVz 2%`!5 ᒤ)z~Kh6D7 ,b~3Xf 4yiU֤ST8v%?^605q_!>~4wnv7Sk0[WwPZ(7]\3C9}Xg٠?W9Y?'/Fw]Qq_rMKĺ99{9'qf͜jIZ!|ɞyBNL>M9U#2"MY@e0ei\u/$M>1/chU?cϤU50p%`Ksƽr3?k"GqL wFy)LU S;<Ʉkإ.c/x?rfHG RSO;\Jl E"?Ka7 H9yS0OU |d^c4#:^b:FEqX6^q|c-3r[Kd]v4O6- ![hũ 'u" ~dfd5^WBqX4|vz2lx6C3ou5*~5Įã=ćˆ,~I' [c?8k8Bh+ RFei6-E4 +5o{n6yD2?2XqJluT m_zcbtֶO0J_tH:q2/FaҾN)P"jdu|Ҍ}iaoQᣳ锻}.C%ٙv,t[ln [6g J>w8f+R| (MVd!WG]xB[-o#TOxo[?;2eݮ|Mk6 e7RlA@A#˄oE%?L[/>v `b' ft H;GdTHql0ZE"ߘ_?ZqzaGwYښ ^7nWh2W'aYm]f+n=:06yf饱R..!ܠ"DBew^6CӂI1'Yk}O1^+Jym/l-y2}ڭPJqn;L_`8{l^Vc G+me*6q@AGSrЍH={,aX HHiH>RΚ*YyX#䦪%x :>V6?'V=YR'SEm؅s2#:O6ma.jU P fG&9B\|h9ץB.`-qlsb׸{}L0OǺ>ء)] Ƹ 8V"hks1LzƠ_w;chY=l)s=I#G_NVhԥm%;DWE_Q֡(Ciar2n)Hf GMY} 9M@wwubE%04Lf{΃݅aN>o5SX["v[C#N2.|A)|7,)֋+U/I'`g~XeˑvI2 \Υ9cE"ZD<> uf~/о*";Ei1H&grtvF(;Mz Z.GKU?9hc4LJ`0fq8wgvh\Q;ӴF#kxu=>~ꔆ]Щt* [$sƮN1{b1y >8j҂CSH{LN SꤺIps3wHJ<qo6I_ioOsBSLwp\V`$2J'%b-`)qz.Ŭ݉7Nxb2"'950?Q  O  _D(WҐ2W +6&KM榱X%6S")9@1cѵԈy,FfҕeA6IS:ާkVS3 ,׭xj܏4hb#鵪ιBSx~hPcA?-]g;v͘3ssOȚ"Xi J|[87I;?f;_*xqiXvoy }a6me~ƹLH.}dS6ۜ/ϜY*) ;aL1pub3" nv|c'I9xucC#j=#L!W:邂p;ld*̶1w1[%`K*mp4Kcݳbڏ^Zo|JmN;hUAvΣsÜM1._0΁Š 6tG):K׎%XLhG˘FWA)V1%c}Ί `>D-nmk3|;[ek]֏[g: T|U (? [|Q ltC Z&/;L^2<\ҨKBE?ay*ܕEэ 3R?9?YI}ܡanEH#n{Jn00TO+DŽȏv;g,=j6VlF8 mabe7 s.w +2Ppw>ίrl:]#V߂\fbw⢆D%֒#$7Q0ݎ$PWP2ԏ޳+527*X%04GՒ1F_半ui iǼ:4E:y}Z ,zVs6'<8nCt6َp4@Z\x܍Pώ^pxOnRogd9Q5ԮiFXu*KǎE{4E̜afN*wXDTgekȞ+W fV>OwPgFpݡHhx%w*1R5Nҳ>7Ipzr\XNH]3&c9|7=v9pG(%T0~ YB-a. 0{DĺOlvSu>ỉN>,࣐3l^iVi[#kir}wB[>p֣vIr W'紻ZAL)F oy'Y3 Sauե * _L9$s4DA0/ž-e2LaRwIUT^fڄa'V`ac:K.' sŠ9 RhMh+Ez9 xK.;Qr\9CVpX×||eAgQ|$D/"1\ [t+^ԢB.c ڝ%5_bcg!;di1x%5Rߛ~fKs&s9HcE"b|H^em 廱c t'$P΃HJ{PLobq-ѓ@V %@p#_M߻SUe9dְl1< jg79z WĀ)Jl̹~[ I-J zt 5C#oP2ײ f Jm [0YfmVM-7+J ,NZP ^CHki.s.7f\sBu2Pn:ngJ$>a.\fٍ1a[^5%ºָ/1K 2f !5!“aԄwv~rO )@tzKxɽ{2-+&od S:{!ZXOR% Fl/ٰe:+뵘B={ p̏ VG K@(*ތ!742{cuҺ&d/'Oc+t@3]H}:A;)la+#e8|}^eOc.SAioV-࿢VIw4{K#B=S+)Tw2 w&gx4} j$_)bhJ􌷋 P[RS3Ass/Y;fhls6mqO񅊦ޭB|B:A6k4U^pt]iNA?҅dnA1\q1qߤ*\i.{D@ RE%lIҋPo{ڛcl кrO) P ؏| %e$1XNf5 0TߧwVe{2@MO#"}USDngf4]g 3xMtP5^jnj`F{˭[&ޏ]dp_ 4%HøXI_jȝ'3Z>R=Cf{d*q35s i8$y—3F@6 >|h+yGM7le*5FZƘ$0s1WO" LQ Bb$ Xa!=i(9/Z2{hikfp c|F9-79:p{ixPfZqT1=*nY1srw1u9t'샕IZCgd]QXFxM̘jeg|{aJCBgc=( 7&bnGDi?_Eˉ/̹u4m^8:{]gRAfiŖnݕV)wb״M+$= _+ fKR:L3M;ǃ +mTcV(8ސAiK^WݒWl~v ļz'Zl}M(c'Po?FU #$_{Dž5vIni;>; <&;6Eyw}7d>uX?P='+{_8 M>|sYz$}Oўϝ?/5Ԥo!5q%[WLSA^@9-X\呂0l-/<)BQ gmyF+=s@*wyJc_Ӿ"'VÓVO=:pZ[[YAQ**D7Kk1awx9WGޏGw=nDw9?{@NA ^9 `FDgQ e" nԥV/ĴNbڪ}DQ߲SмDF }K32S ߸U+<niYmp4_̼bb Z(1c{}ʨͨYkPs5>: a+ bgwI/4Su`Wq:ډT'1J-IIbhTyvK9 #>ܨ({3RhIЯ-u,|T]/#)O@+ɿc1T\G+{㕩R$a. Vy)%f%iL!ư0RC#yǧ+%d^>GL;\pLp.a@zxvIv'33rj')F`Vm0߾IP,KccC9̥L(UECb"NMi 7\Їmb} ˃&m jcCPtӽkG: b]Ik90JrhRR_2׮G28W|WtJ9o8WL`K6c"1- R20š2:!b(Su>gof(Cn(/wz(/{w&=dnφň KWLFAg3&,U6٤#.i.95Wd[&Ӥ}48K T#ok6uFV^}z){Y$~V.nhZ,}g:I la~6ݭ 9g|+1(Hu1v6NJY&!Wb'i%tdD JvS5Qǹ>Gвhث^x7£Io{EXLޥ3FluSZSD6aZ: ÿZZ; l>v[viQĚa[tX {eIA Xs4ch6uHz1ȸ=T3Ї%5^e Y#W" "y׿ "k2KMm/|%o| m*OK[!7tcB!ϥirN|6%3HO:C,=ivh&G"ogb"=`ũϋ39c$TNy,jupޞ*E_kK*7r_zݕS =A&:M5.-!7μ!31^MJ5 &vЪW9GJ,"GiJh؃ &_>/G~sw9|6=dHs Bck 4YHc/ !Ck^_(th\o^n Mgo&wivWs7؂7/2sIk=ݗryb0Id:%0C,4r y`ĒDijf;Շ14 F6-3ܝ2&JH+|Yɰ_ˌm/Z_fh_{"Oq%8Nݮ'MiYݙyDcsC3gd`l88㾻?)>e/jה/b8B6|r=?C+OJ!b\Q!%瓂5kEFʳ=U2|?#ULm;064Z6zq C#d C}hwswM-ɐ92=mMT`T7+]## = "1 !6AjO˚1pAm(+ݘxѷ,ieE.x` V+:iq)PP.wu[@C@jyR~>ϔ$CnM!P[Gs;A[S[ ϔ>Kj@20=_gco?=[i\K]b;V)s0FZgֿHp 'bߟϱj_Rx$Z5r4=L\m `w?eAf29nbx+47C@AG*D7g ^M$;Pg`Is?MG eZ̤ "aTjLbgHx܅A&&_6p4P2"5#STQs/@q+㉝E&vti(nr(NrȜ}8 J'# FP{dݝe[5xICe|~ψi ("qʎQ3yu·3k)x2drgc($sͲwWo#l&\w(q2+ /[ ?X VϢbWP>iUJ#|h(c,[ Q>(a`F& JHAQ9C*%~*7ICxSq!FhF|$z#cMK1ԟBe--0DC;zU;TjM(/Jy@W] *A#f{QMౙ yݯO⯘|+?(^96on\R^[jʔyfvx֋i"fY$B+i*\[k4,WֳrT਼ .FDܢ4L?gQT+Ut߳汵:}%/}2 Jp.pi%T|"QϵiEʇ9D dwW; :{.6+f]˻^P;9  H)$rn6 >'E;2P0YˆۑD ځB*q\j}x6jW=rf``R%'Ëmv0r?Ǭ??S/>H>FPEN6! M%q"iue;NƵ%!ǧE5wEj\3 BߜɘHЌGw];kG~Aǻ"ꌈȽy/ks~$M:3{OGgI'Jty2SkCL 132P*I$ݶ7j-0WtLXuO2kǟd >X9ꂐZmh!R^GpqSmp{`|hQVJ4I ^/-ltR7 7zi5djxMytiV*`*>Im>(3I8ZsOh"dE{Z)OHw!=}EpM_WàN8->Î-n DtRz\-n`hۅ;Ij\Oܟ]o~(h(dfb s+Tz#kǞFrkL#!LH:VxDC)ce~LUP@ji~p|(jV?@8 08s'K;4x:b}o:6E336!.b Nuc 4wzc&sgwL! bwZMTʡ2YO _pRF,d"a t0 Zq 3=nsgP9 )h1/QU0FM*:F \쌯~_aރ2<`$YaͼO@)NPMhSqZ?19^+ ۝:Szcyd=!O=Vɿ>z\rVgϡᆕD cӒm9Kbj Ie3ݟFS8mn4ӴodhLbbNkʜ,wx\ ߭ W}rv;6ߤgb[!9.~ik+r]Y12OcU0*^y#Uߎഞ^ӟ w/3 X1epEA>7HeΜwƭw@ ۦ8] _yY%?O'q\,C>}zJ{w$Nf~>>*n^Lo{`zY#Fڂiy^Jmާt|WQ>Sbϟ;yZ( DXx$_B}S"7]'bkӏ8Z@g\. uQNb2{cVR$&FWZƭHu;/bi;O_Dk#5"=exO,vhw' >%FI>@F?.5 |+{!!m0x%z3-_$⇎[Z?ocsB3>5Yvo8i{)헌Vi] Q~U @ƙ?; "w` RmD{R䂘 `ΎݙCA)[RXXF @9c%)$_Lh*i>ûYv ӛbJ:[1[EuaT2obDLAu풝M5G<'\[lOF:p}0 Xd,sβ. o?: ҘLo-d|,McM2?`Y[_w;OЮkLqFmQ mp4yZS~fti~P)BCicw~En9rt<nN5߃\ͣ]͵)pNT䑉~x{48}]Ie&8[뿲bPe0>1h']gٺeG7؋ov=[#VZ@{4{0j&($4?"9ya팘1FhaTM_h Ecg Ngd/~ ]LZI`Mԫk%ņ\FY+2:P6^dЀc%b=S Ph -Tʀ(ep΅Np-DZ0Lɛ-gQMl%_R -,mWЎUÔj)wՂyJVp:n(%IiiZJh*)cBJ/~kړZN?Z'/RwiJ^WݍjH*% B% U~;Rʤ:ʉT)2QXJtM#QEu5$In(`:(MQd%JVhIJ^o U+$Ѧvv#'ޟQjn\0bt$'lЗ n%0AEXfP%D^C)*eΉP k^CE @y~ךt@Y$zkSi궆Y m`LQRݼň-8tDZ8Р+%i0j^GD L =BlYD)Ik44ŧ#.H3dWWо5u;j39VTf#]TOZԄqԀ5J#owa '7ڀ>0iҁ2u;ܝHu'YL(z.ꋙ͘q/X9J,WqyG@=K3fDEi\shv KmINoH@4% :Fot3e `B iGIuΰICj{6x ˯Ju+K ʀ :( 8eU`/L aG)Rjc:  *u^euf,'Peؖu`Y5 %SGm*b,Ұn QtݲJmoe.l@Ӵr*E@JSQ&Pߑ  NQ @0vj&V) AL].A*C v@)aھ1z>F@>n NҔlᒙ,F3J 9Pj@jLaq; ?™y'6Pn!ێۍ86EVi7@iK씁]6TT9Q f>̜ v62}:\_9p=:miw$PgԠ(*}TXH:k,]('&o٦[$j1" e~;r#O&W6,K,1٨cڿm1t**CQ0UPn&s͞~[IL[/nlAJ"VTPX[ېv ?`RoZW"!G`L_lWn9Z9ʓf*y; L N @]ɝtdck7MaP9pW(ufS!40tmb Gɬ$XR(rT.܋qƩXaȕU)KTh j8T@?Ğ~$?tkػMT~*DT wS*I8_YIx؅18~1g|С+Nrjc7·LU~wX.t|$ 2w}Йt?i*mxCi䅳Z7|vQT2ov/hLweRUH;F;o0N\OfxO7t<./lVp^r9፮; ݋ڗ3 l:N: qż\jjFIGCruժ$~skPiF{b-cr bW/}7*B4N-pGU{Qv'H wJ .3@y|9RjZiaH^#+`%A㷠4kM_~Hߑ(;d@]O_X{ o@]p\ݪ= tnAqD6Y @LElUB!Vfz.JXԙf}Z adVQdI[SU]ح ~> 1'w}'(%G Dp.H){?x nsR:MrWSRObcQ;x7YMJk>Mm{wZw>uvRW7]Z8g"0k: ^ lR#$D)Xk_~R$w IV>"*"K\Kf_LzHMGfn牺ޚ­hM5|/U,r1eGww@߾d,ϯc0ĭmfRZ]v)@Wr1uob#Κ'_h/Sx+/v =;g|Yo9z n19=! Uj)@|]yʜ3,d޿tqe73֌ :B.[b,Ї 0.A[MBY]z3xK1覆U- Mq]![ұڈ[MJѮjzoC9[ ,3+}y3EH܈2cjRj؍J >6p={?3fV`SD{\I g~ Qdʑ$E]M/*tF\h*j>{[l7Myѭg֠J$ˊnݺ\[>eT=]}FKyCiK H9t;X0c {/3"?ګo@PfX1LL|WG`鎞.qA4F )N&*2Hl8!縋H˧%sCYiQ,s寯ȳVćY(V'f-C:Tiz3EGnA R\_+Px{f'Iɩ0w[?$ KH.)WT+L5]/X\4C:\qj0IOM4fNّ)d>'frĘ^Ad7FLG@;H3 6,Bf͏(8/z"C5dg?0C1ĝ}}ey&Wzc``J3*pUܥði0 @-ђ"o/CreOhHnZR z0G6__?`^m&2^^hn#D~Qus7С eK8mUm4N j\l'|gfj V= *GBop(4LSѧ3*DFw >8ue1 cbS1T3FSBV0SM|t.#Mx{,A CGN)sw,K;5>tԆrڻ˱Ѳ^w-Wg5́9TElj/׵G[>rY=6e2]ADr˰7 s T,~]?CFֆ'N:#4y$aߤ ٝimt}=>ZNfFLC'ZrB ٠*u<',e$? 0g"^#QߴwIF=䲟F7u ?SW$}!G#I!e`p$oRB=W[(X+ؐp7Ych(WOdUbys_UzsjP*EkaS&E}Uz7TU5N5ƅC:-1M18m]Ve'M|ѧبOu^Ƞ|d&⛴e^'[ֳ"__ > zxɉlbT"knxtVG#)]ye6!'se,Yk >6[ho٤pߕ(>w!-e}e)25\p3bCaɛGxFrabLJ\N 1 OMeb'l)*+=4#k(?& nWO6d5YOS Z+)*U%R4fE]Nr 0:YBLPprPk/HxNJYj9#ߚ|Q`f 'R:Rk\ׁg,2@Mspo<%iצZh=}Es2{qClT'@#`1+59G 7|HF6%BSuO<Դ $ ?iTv@ZFf^Xc_: ~~44F ɸA,Q mk(MNS;n^I/M{ jfq.s$q5X: :N",i{ԗft#] [P)H?[VK*z2K.t1m) xm9(XWT:Ahhu %c:x"g$y kp0*xczoi-{8pL>2T1y/ߞ/v(n(+nn)̾z8S^tEI#,G`lr$)hֈSd×E9foCQu A E vh.u8K\5Z Y-4'=\ RN*s҃2c}`3=KpcL#'C1f: T)I PKAL&h̡BLeJ;~4Dg x~W.솯q+T]>Khό8PQge:":[0˰SmLgMѪ"@&gyz} Tݫs>czT _Sg )ZiGhdf#)^KWP2ɢ 8?{4L-R> 'SUIrˬQ/5"'ۊ˴#i#Ҝ/V~=?YZ#T=vԪ[>鬗tR ޘR| 7\ed $} 閯7 l8&2Gu,>? *0 `@]=={rvTwWx+?(9^KT*t;ȹ Dikhi8g4&GW9-e X3B颲٥e.⡋ L]p{:~Dz5l]#5fLihm@ [Z>__lW+ 'R*T.swH#A1vԂ4]IC||*yt]˟mRY^Z1K͕'@QpuK`6Q\^[)]lڊ%CyV CnܪܡG˨1ԼKP9}2Q Ѫ s[&+Ҩ܌;G(gG1*kN-m1dS !ZVYz-k-2N׹qQͿ59m9l#k6h6l5ker&WU𚃥|tJ#p3c>;! 26>(d9jYoP܎Σb8  + i!gTQq2)ﲊ=d6x߇l )\^SƬ0nx`j(6qyj$h+="A+%x˪mA+R %mPM^EFN"!ʅJb]\Rk{YJf?Wx L//nGdŶ3); )iV,ruVo_?=`X>Y PKpWF7o[{k1*j)|kɃ]T&4vxcKM"u}Yj܌FH FC##8+ɮ s:FѠ{]X?񶰢ܱw;psZvpRjFjRʃaxRC@6ۨK_Mŕ3P8p ET6q̌ChDjV8 >{%ĢU5GGL~V2ڵj#.W6{MS?@9zҍ~>̙~BxbX'\l/RAIM= 95QVq`jeD$ib+ÇU9S\ ƹsc(N@^.>`mʇW98\yFEmBwgyD<` "d]dF#9/$%3|XpqZz[)Pl5^$ wrn`}fRr^_QhQIP H >Y+0' 0{ufi_u} aiW yo}B`بj9ʅW ZlaY7G۾T*LȀ`sasXW peY4L MddKIGԁMDN[LWjX<bEQ_++eK ε5D ѭ',6۰*[̞BF$YHrm8FA>#`3޳v}c-ҵ=w+҇1fgf+"7nPas7Z\DO;}W]ʌM׷(%8/}]N%̩#sO*)+Zq:o{Cnd⃶Zae?OS#}Z|ϕcmvoĐE<7 pizB]l"י- R>0?Wm}Eۗk!E y~:+sL?`}K9= \t:hTۆroE~"bqH83} Sˊ*XC%m1(j Fϰ8oyrJJQԴ 3|PҸ[Qq9↳U ay `"?8)AW4 RVw5>JM0Q(@s4> RKcp⼦8gpTGEy zEu]) ص@YYȗ2]?չ6x`lgY4(ܪ}i5t?Чx[pT5`xY~a,uenl6-ٿlR j}:PPf._ޕрP$ԂݹPwo˖ЋilR ?4]%w:iM.aW8RْjՂ*Q`a͢^k|me[HK%"1" *02߰~ԝJ/yo`Z Xͬ9lC֔zsY"X5}(ENE***?N,?xr8dsO:˔F8qu%]I}6؀S+b()O{W6!YYۀFÀ7c-*u*jIvk%jJ+U!4h4q}r&Y{DW+=lӂ:eTtY:;a#;X^o$یj\ˑ* eCZ]=u>@}ל*fз0m+h1Ov0ZxPb^rѐ*dZ Źdx/;abE=Cy.^9sT *}fIO;?UȌh[$!GW'[dsr~\+s Ga$ :&U9|ͯ^h1$h [0H{P]D"A?fѶ `SX3֢A92zpH(z#WVX:&kXÓRl Vһ;?*hFm+6xPv@K2TPuJ]IE"o Gʒ(k _$9&Thb3spf- ټʬl,p9Pz2#չ:X[-YW@jO.mȀQdn i(=+ _u;UQ SYH.=eb V8qG Dbj#BniYY3:OϮorڙ7Jz J sMތm\Hl;B;@7;"Xg#0Q*@@g ,ˣc<ۼrVpoݘwjbJ~3݁"$Kx 0pXE0I{L[gB kgU+8?s# x/&_jdtZ;1%~]1p}r cxM:9 J @X'0{Ξ<{~ m܃:Wws9)CrGnWe_EםBrDm[~w~'EȤjL4~T>\1%K.%WpufNTyRR-(7Zjc7?j0N{$.@wg![\<" ocKfP~}%ϳEm=H($" jD;z֕bl38r-H#fl`l(hX.⢽>>SVfh vBX;6o/l~]l$rfHJ.L%Z QԢM4&)ns9?Si{wPF =N@{(`uγODdhgsA.#UIqٸZ5Ev(0dE-սhF9M"(2Cѩx0!Dj,Qh Wa{E>\BLc?^ԯ&7dL1r!8IQe{7x(1L/;PD?JV ) Gswk,-*'ASwG REjw}_}-o9/1[]l*HGx} g Z)N0a(G_Fqjp N{v]?W(ӪqhtWn]!prkJ5khuxmʹ JE[gdDuE{ )gBW+c[d+ݵUW)-¥A+0%Sͫa"—!~|GMԛɢ 41Qf mY3iѡMC%~sz^ nfa~)R p-,3YTɆzheT yz9v*g|vaA`!skϡDԾo>f"R6EíΊ ]K@J j$ØKw0R'Fܞ U3w=|k[/ p pqɂ]Z;xC0\vwʕ[;svT5y沱ODD؀莽˲4(tXMK0#87V˜v[R{GEC xkǖj>"3\$ї3&'}Tz+3q-<[$6 P* QMԧ\gԝn_4;{r?RDlx5Vz\8)7±A\Sn̐j"zOzɞ/{i=}Y* &aIdIKӭZs4Fy{,Y4\0ۖK۵Fp:{ )/frΆ2U@ZzkAdآ)Kpw?U5X52-eW^l mJtW-$$t\-/xwӒ|;hn͹nUIQɓ|>ސLwq0etJ;J\V@[^āԢe0Iv SR-  rFϞeD8e}u@l w>6v?b]Bc(!Ay-7ӊ 0)'A˜o«Zw҄sĬ ˼0TF=BUX.2OO2e ,x? ?Bxc c`E^F"(O^l=EO,X)[=cΌ9dZ(G3?*"e!fif z p(b[hGBbs< ڥb!*(!3,0z AK/Ә\zR%`o;)Mv9l@#0}0G++n%btu"G wޜ܃|;xz;Y7 'F$ϵy0>83FfRnDܘ*='|Cr5Hdg`HjfkƽaXxsrX05(zu0)i"@8a)>*)4 2_Aʻ~ܒػqfG_{ėD*ڛB325 qpǏZ&!W]NkZ/*pRj"ۀ́Ղ1Ib0#x[A B N^!*q>#AKW0su(5kBgM'3ܺ坙z1e(P_A#a_>W(jOEpM90? R;U'f Hl *%M|9qRv:YHߎk,~>A0żZQcHgbVNqFYV?6fO;@xvJzXuD'~e{MaX%;$I." D~.i0_yָ옟!sJ_?ux쏒d{Bg\W^X/سY]c廒-~efi3@| aR3m7)uJ!Q!iͯ?[,0oTVM]*݇g[(rU5xװܢɠlIˏ}z8mE}Vy,g⒂+a&(%'Bݭ8 G$>wW[R&~0hPuv1>$ItߓJAdE~Dg>bz4ϟͦА8821. oJZ8=cS0U.x].No^._&s~wFѧ#\YsB uJf~>ԓEc7h[R[7.fUeVr?`ARq7Tۈ[lg).gzЭzĤ(v,4c͌Bɳ(bQ"ag |5&e W`m>#9Z%:(TJ9+]t2IB6CJpײ>jjf2P5`S2`J{lԒ05 T2qA'N=O^ۛНs]2o`oևllV=|V].fzQܭ7ۛ_x{tםkQWq{2fwv<8%#c1oпG{)ݷ7)+jv/8Ѹۅ9X*fOx>G .I8ӗ>+w{>Hq}~|?w/?YAfG>'O x7 \v7xVp;|^]q$k )p?пx ]&yQq%hK$|RxpT^{;rwBH?@ l};Ζ_Hb7 S UOJ\t;-8ǝLw揻 _ܧ_xN:Mvzo_@]wq'wܬGw0.Gw]o=;LGklVٺwmw1}ei:=wF&u9og'&_:+|t#˿w+ns:x<1)q>B}C],>^٩~p_ҍw)UhM /Monz]f$ ų~T'pI6@V F=G$ǡBN=-aC>ydW2*d1l 37>)K%"]y h?x䇰۽ȳ sݶ'f0[#g`{lw?t ͶpxtЏG$0Eҍ5pc/Bsp<9y29/hAhpqRc{o؟.;n7^<(?S;@P+!A\*SHG q9yei'PE!Dz3晭Qb]o.{d(@Ϡr17O뤭5Ҡe\ Z-h(Kh5 Nȗ/uzꥨS2&}HFd04 Le0"dWUT/_IV?cz Ww>HxQ|Zևq??O=)sa8ߍC3q *;1 ۻFo{ ~F5c5<̌?&xu/7(/A=\wM)OlG@w8w^/>޻TnO ¯;ۛ9u_0?8ܘݱ7ހ53܀ uR4|ۛЧͬ<)-0Uw;CWa;:\|"YMh{C5<ݿ0BiDSu&1֫vcǫWox3{}{FxOg~ C*gΟp@?6ї6e n0IS,.O aZ|i?̰c0}FK_o4e3oօp(3`}|UO0ᐶOpV`fbM߳&DӏL;bM:cS&cf|;7; ~Xaa*jܱ(Wz _8B=l@ӝ7?w<[G求!; ~k l-$$!m˛L_:DR҉hN|E9䅀2jlp`pЃwT3L$:_,l3K.i|zŢ6JHBA)LĴ@"h ~7|1˸,^&Éf" c>3g@W2Yc2%XtCE_pHs'f0=+T`SZ+d{y]uˇ:䥊Я2?l|y\&β@oȈD3^I,AzsW<@ҜJbuǟ\ 2x~f FƜ>RJĖ_! KKfl_GOty ʷno{,2mX$v^#(,. ƣ0iZT6=C( }*Ki}9 P[R>mPBSBM1=DZ*T⚧&튴CMgKo{u35}Ӫu;f0#Sz(؛ߛ4cy;0QH{xFΰ</ Y_.^VOAZ`s 8e~%-FL5bB&Q;gxgSdX)KB {!#!`w?-`}bq>ƍ^_jkW|uoX1'G[NO| tQfhB1fZT\ #?8X13=Uq. A}\C#fS ̖}?ZOɶ xM+{{OWA¥{"S)|ן-5\\4ss x{-cx#|F»~YXQ?s8]B(=%a/szo `W nJC᪩cfá吁cw-Uy96j6LOY "9ܡEGtƇ,,iYݛB!A_ /=gDCuB')i^BOzW nV'^xa?CO+e줼 yvlM2sH7q]QÇZ86VBj IW+4Pa(r o24*y?Akz:h_PDAg> xبxQapG엍"2%Ž ,ɝ qs [*?6f.sfƕı?m] l <؅vJN2JkxgNIE'{cJX_}w>/(dʜ>>Ԁ b&Fl*q*8kifX(Uog8 <Ś>jU1ϞN_l)<im\u"D$HZg!懗6X6J>S$dg.Ted ?D -Z/82`ha,AOxj0|),߅*Tx\&Eczz3 VE K6FGtn W*Lm2e{#m_yZ\Ȧ5Y/' #@K479;jw#1(2v"B^sMZ&0QdUi`e.ֈ1"m{凅@_~ԕ/?? v1Sj"!-+*ӶݲwR0O|Դ?LDŢ3:~L|@/| "Uv(25}S3I|y_z>$P%p#jyJ t xal[UYN*G v-i~h],-G<:&SE,NX,c" EzRcSVhBd~y(\gKpX`83 l A:DZ8kAU(uZ5"5W=&Gi6Sy cbGac]pݎbMDP6ȼ~~ Y)!a_~ouʾE6nqz٧ g f"NIf>i1L1Lڒg1-GrFq_ʋ収X> r_J0߷7s /*Lf3>rNPvub=Ç)\ !ru`1f+vtTPQgzvt/Z|o-) F@> - Z$?)^Xެ ?בyx2wի[H˙=4X:k*|*_ L5wધ-m' < ?gnkl$Fr11%#%5=o?KV;ɟ]e?v?~Nb҇?&IG#٨*Ӵ) O\[=#$M#yc )<~9T㔺;lq Q Yñnqd  BQʆԅ'3(p;vr9p{>S& b'D0"b-> DDLr&ïǵLA'[Y)f^>Jrd7VobZ{*l H ˰]Ei̮58\7D5dcOFJ9@z(۸|e)&Ū@+"jtZAD wC(9رXtNTk4?MXS'/7} q)'& N59k1t!Y|&΀ôѕ^_Jltg3ҺoUj'@*vW6ŘHN)l9ɽ$YdYDRy* Qd0iPLqL+:'|urJ؂!n;~&`lA v{øs,(LV<@}b}O{x*:_pX \y2AGr3C aH}9fۿ  T\* u- d\a`Z~EPSK? <C"lFyJO 0HM.(B-/2(S[V̺ l~*W7/c˘n|x_a3H8WDYuD lz9 Օ``{~'#~EYXۅz0f"!`՛YJ(lSV,U,d7(E GgnRY /1{ҘOc}xz,D~KÓǘ 5:`*FW,x1Z3+veՖ"s|6FL/))|opGc/ 3&YBLb`FgX v9"=:UD5m Q ̮<ERg\N'5=~P&,iXäÃIǃ"ha`(?M։YLA5TsvfY~ scR c&-X!2Eţ*8 8^z=%.I!2UŎr0O%aL΋H p2; ̖N'e0o竟@^e q!mM(+ 1~}<*,{f?΢+<‚q`2O h*zmA&֟_ȿ~jp(?T%v._Ԙ GGg u wց}(FTR{8K;Eepi @iGN1'zGWQrIr` pNcA=Aq3VPOųJfwS[Gq , J4{LmPdó4R[vĮ2aoW^%l%{5Uסq_ooT  .<u `A$>m^vŖ ?wE[ud\&&%ʥkrʕ"Lj9bUXr0?.G<TШ6F Q4WXI{P8><.c88Ʉȉ}9X5@rA߇sɜ`ɼe{0G_T#V" 1;cCTȾX,@=ZF_]:ygC~E "=5#җY`\(u 2 JY}uj퍸 u>S׶~~|&USX֛ N3?QKI 1tG sÈD<ȓ2F%‹O p~*}U/4W9+*ҧ!H'|o_PF )!(d;wy?\''}}1n~ o՜ɽ.Z!ʴ@>[1jگѺR$Hލt'%/GN!2G{-j=mwgV;˪qs.[m+Pd-G2{A' 6t߅.ƙŞD5|@}7{~d#ud^/Hކ;l~H߁4}GQ1C%4ַ-十18Ep9ÂK'FYUk,|+_m 1uOo~6VQ^;Cj9 U ҃C?%H+mjCK+.5`*Ŵk $N^Xl)6h"\)I UGRֽ֚˨*13oؖ+k(uB[,egjx 6#zs.!ZY\ބJq&By=y7Sjx:ϾfBV/ó6X@ũH56rJ~U2GҦL`pi"ȼ0|\ fzt3cc-4{LoiPkIsO6J&XInOWIV3Obó*j joWH1cMggf&i5(ӲI=f9#uIb^k-1-o!Vc2P ~`kEpyM9jK(X|ZO SBT;`ТXZj{pR""-M*sTO6Q|'NkR,:S}qm'c  _Loo|`˺W+; O6%P^ܭ.6{$R]oo~.Uȵյߞv ۛjI)c ȟ%Bx6_FEiwQZwٚ8jR/\կK-=Z5Tm۹g<}+Y@5[Bݟh1nd@^Oa}:lUWJ~*GR30㠡 Jnq=ܦh!| PEu1BPcVJ[Ƙވ`~t1|,`b;{o0 ym0JZe |M=%#3Y 7Xa,p}I:G 6PC?`>p:C`br e}wM` nqGF gfn/5I> HMZYNt-F31jgEn`q-0Mp_z[ӷgql#9Ĺ9<>q~@FSJdH&3!(2|x.4r`DZC<9>_ep<PyB(&?ztZw!n:%藍u;X!6v$sH .Ox~C%L(m"5cQ(x& gDGY,JQT5*#k/;>i,Keѓ''_ 6'ރbY=Nko񱂸դdzgv⧭3g'R]7OPa:u1 245tBߛcu"v @S63F3o<<>nzv +RqO$Jk4{'tĠ׷:EfڊirPoR AGC Un&@ja!4#)ҧ{]^YBsvhəh` Kf&??6B5yk}n+7tw^Nc',``ҭ1q2reex'ZI1lΎu3'gd`[?1!2NJv蓉jyJZ{P "xVt(`'pEރ,Ur]@o"Dޚ4{4RN:FP,♅Om+/~ @ԑ&`"oETk}L($%CN=xk5hRUO+C9GTR#MwɎ1x22Vh9#\wKMr"XFYmaeW {ݳXAlλ"SηUk79F**O41pI0I[ < x˞ԒjG7 ?:6U6 "tvIE`^f^aww;O#5rQTuj^Mĉi#Tw .Gp ֢gl /\10Εj5 ;Qz{W49No:d ӏڵJ }.:Y G0zh9ku&u*"HY-A0{Mӕ:`ږ-P\I;er%.=ÉRP"0&,(9(@@A ?Klϯ-gډ\.Yd^QF]Z0n\'afZ> e"`6 3WwG*IE̴9;*5 -s}?!w@z͝=m-u{8z8gqQ뽖Qaɢ}R{^ oaP%r5sA0?猶fve>DϦ%M>[=]5S]!]) ?_L%wzp(aŸ;bdF.j@o`/2,|܊uU-6 Wp`{Tv]M%mӫ-t.!`$>lnˆ%4IQ?5,}ҏqEN7˷+"&\2o@ozÿİ]E}wl^ hvMlR {);GăB$nBnIs Ze4C 7SN–! Ue5Ma7,Fo;__  ZMJ<|maEmd4֕sBRxRLtNq,DDa 9qY.踱SUlS6.,0HxiԼB$`;/7iOۦiO6N{͍ ف t= C%ROH+B:c!gF/i^'ܽebRؘغK0H4=_/] ;gTIYP R~-ۂy$_پJƇZ܎um A Y+0l*tg>j߰xG, /xȺl$m^7(E1S;phM/ŸӂlLtwL҃Yv,%5nhc-,4 ;u)ik#k}zIMLV})A>Q fAjV>5K 9 䂼)!ѽ| f5׸Ot& 5MdhE F nС;96?P̱/U;x`II3+-*ԽʼnI%'(xIU'gYr΋r`5$+|h7S*Mg Q8b}'c#+ 3sc)4?/c3PPJ_'IGuޅ ƨxL`xƳo\ DxJ-a:`4)Ė@yd̘~&"%ُ -&QlL'gP=\^OWˆѭ+ѰmaH{oA^1h# "VBy=3ѡU`5J2"nɃgWUsuj_.Dl%ST7 0Rl2#HD;f|%UXa*핂Ze32l~/l BAa!-FZ/Z˛~Q\v,Șo`R~ F)V`wm jrzlM>=EIskLnd@FW\)YP6}23ှ.8v`  756eL 18Onj07p6K>f03lºՁ@ 54ZD 唯 [rV%݆'fiohd[`mBK$o[ԷQ%K ƒi> QH{ "9ԟSN"(7]AĜSL.&=zq=^@*_g:qa9cT{J LO /ŞXÀ1yX8F,AzQEˏ'՛$ސq?;^) F^w߃N"; %*$|Q9~m_!GPdjڌ5~9ʞ4}?R[p C-C:54kրȮG`# D\&c Y_[2\(7bM0_|1T /$ZwGҠ&)ٻO2}KWoz,=Jupn}8y&=>RL0eB׹iD76%k1,al`IR MA_KQ&~s]OQbh}2-K˕fjp]ĆQ)&ɧ˄O{5'ς98FyLzR+KLH5 [ Uΐ^^ fSTSa= -L@)@$ǎ>2 (]J`Y(X`[Bӷ/*cD7*ZC8B-Q_[B$,G|Xst;QxU%v)(3Lgog՞}Yy"mN:M븨2P3j 8QfY NΰBs5AK'zR^ s̈~F#_?)mmV3"tɛ`\b 3(!T4#Nَw[;2͙NVZ̴|P_wx hx/jR9!bV- kX NyHڕ'iC>gQR-W˖D~ FWw$v7MakLK<~HnjO؃#R#ƯK&2;?_w->hmdHEN0L"a^alvdMs?g 1'l f><_5- \-'hc&\k\׬U ;H-ȅr EE&řT^:Ŧb6Xz&]P&'`nTubN3tt2gf`2޼} ׊S7NX)<1hqfو(/ u-)U+"Yq# ?~_^e (W0/95Wn=ʵX$oRzm?|l/t!eի{O|#&chh=)J-#7Uw^$41:7|8[[} әqG؃3S _aÚIa`!,q |<H+A#;+\48$%)(g\ٌ:N>}ΓWxZJE_Rl".ɣ>ɗ&X”a`|Na-fS[̒'V4!@6w2]O~j98OO+b0t+./ >}__ 7{3ueR]!EQtJWC}>D7Y-7_O-Ո\R-;۠ڙ KC2jY&xfk a]+NWKJ JX{aqy:IDͯS)a$?"?}"S<}.kMC@4tVxjPBzфBG#kxV9X^]4"HR `"1ы}|IOXwo<㌂$cyzLe߾]&CD=,C1%z!7~#3ww1>o㴉+nlc}.P03s#`}5lv&k$${LWa%A_P2[)ʮ$~+)Y\M)qw >] <^~Ez w%O }B4 9!3nWQƤii|AЀHh2,6AT,gޝS)xc빡X 0C%6QEQ l)&Ԡ(88oZMֆ@(5 Fa(fYi@ρM~78Qf nB2T >/R]qIcj&`fafJ+vz\lQx[p3Ş1`΢3?'gZ_%G]2{YydcOTI. , *5'4} %5L]Rl3lsP6h`%,pw}J:THP`o@mS\K9^LpvsΌq@+AEfH>ɔ@Ad}6 4O+gE'BbcU<.WX>~;VnvLL:aCN?X4&gJ\ 5ip9e&Sixx?Hi=IX`A= =0{l,Cڒ}v0\h&{͹c;wBO/ΎYY ct-T 4LQW?))cƺ~gK !; w!󉘮%[!0낅2_aZm66tEyg܋KO%[SqH3P|OwI~MXGk=Rx;hMeV] F5`@A_dc׶շ]l\IB=sB̦ C8PĨLŤrדP%7 Jf\*7w\f#厒ɈqI?,O+Q޶w֌Θ17bDsXjuG7KW!(O^|'g!)l%jN{N4MmK+$0SvT8:%wXѬ ff4Z0OG_`XlAg V''d3 v1 ( ;'IE)A^I]M g>/nKr v\ O3ږSY] W3!Y n|RCXoy9ʤ8[ܡ(eqeYr~%s^].muPe22깈)oN &3zdiϓ`M {M"<>d}#D!9pU~ Z\?S{dx{0mu RmwZɵzsޏf@#p~JnTJR>[L^@?4CkN&6@1?;K܊}0ta5$`<WA?&$K`=| [^UQtsHQT_ <a"GErބs&wJ~6Q%S{=TrK()@ڱ/S60BC{Jz*+,BIY<% o{҄d]6C=lj%{.ٸ8dk\:XQLvO>RkTz&trL6懩q}fT 'sh7#rAq+߽ROE3.sgt,Nv0J:157M);ci&7{Vd㭙:*JLY`$ɭ>YB">t]+h9d`i!F7 &xй8)/f(@R^gH1e-;;cTzRh q>)JTJ)v50np 0AJY59ɢ@$i""K%⚺zMW5mBvJ$kjڣܚON,XKO9H Հi0E9"i#Ȳy ncHƲVwǯU2H)k-'n`F_`H\q~>N HdL =:; Dg}(xN351'T %-nZxc*2콀 HRIt׭ .N' 0fv.$bYA}o3kecUT8dk( P|Z{p[?nUߣƳU+mDuk!а-Ltvna\nۛ6 Ճ]qvU;JOWbW;f_C('`q̛ _dgV[LhtD##,wPױ)UjR{6 ]Q k,G1 eɍKXE߁2ct qAH|gB8d-Ӻr?1sgʌK$' !IuC%U^B7ƳW'SGYᩓBR"M[m O޿ά ӹ 鬲< f8$HZ*|]o<}JuCH%wߏe }/蠳G i{Y+˺w@H 88m sqoUA-z޳滖,ZjZkʹsX:\^%^ow)IJLpF@g[Pch+X`\嵟T/vÛTB+OYNR<#]zq3.sVbˋc'"(=o}O`e,wy"[O"h\݈ZZnc5sB58y<1257^ڷHܫ)2sCuz9Ô{ dJQ#D%1}]OjSLQ"eѫx󅵨%ߛw;Z|-'E/ mi k׋@[vvkjrJS`WcK"ZHyQ; ;6ly}m:?]Y+ڊ_ZyĔs-~;0df{ ?-\b $~w#7]W\ZZ"&v8wkxi% l8Du`E_]Mk9/=__*bS/N+L]q9j@ž.zڼըXy]Vu\ZQ!8 &X1+b)/ַ3mm: n]/%,lcIk흧g?vZh<`H۫c̷-L-~pŖbx/~tRFeo=??GXZBA~FFr}qyʽwj3퍷V<֓o׫vtSًKTn}~XM|Pd{ƤAzf.ne: ĶoW@Mze"RWɨ ߎ0L< R-ÐF@ JF3 ]޴ˋWV0u/187kz20Wps+7yn:l/e k.^x3POcd=7ZtGSr@TPTW PlF_#}jF*B|[?-v^5}?(h& {>CaOo5kUȣ3U8~9&4Kڅbr%bN#K|.mz-r4;c+s'ƇQvPԷ7[VCDűu 2jX1y1]D>V.w}9ҏI g+cD Zğ@* h6-daX`u4t+`| Tk4G\o{ܾĿ]xNTi랯k#fV[c'Un_ SOYxc07`It|aC[_@zj4>&-S<\-Ar]yeS`_L{dK3)le3/io J^Q@GX̂̊k{,۠\8Qua~aC'!9wN8j& /˶7ۣX{ڌ"KHw.f7Pѿ̰[ݿcǻ u3#/5j 36(, 8$Pn}E)}guǏS\w}F]2Bl 0-_hvŢoDн:O1-Њ 3\~9/'U K6*ha/˰I%ArZ&,H~e\yAJ1P g5bb9OX_ x̟! rsDFݺ F60MC FCS&k+\ߣ<(nnk RrHi^!'rz|"{%˝P@NVl+ݿL̬9Lʯ@2< 1&xiߩjkVau2òY[Yʸ{ Ϛn5l>x tdPRȦFǠ+7dxl\ C3 ",@SyJ-"V5i!9&eoWPb|?f&JAd\h+‰չYir%y,482|ꭍ%Z.C !o/Cފ}} 鄈w@jTٳ]['EPZ' ߃i(2y||G:za1h0[fpsp`NWK6-XI%Լ(/EZݻp0TT% V1q\9ghZqd,`y6G ų~Ka KV1D7T󆄂(dɯ6lzP{xs(rr\%#S_e0tu3>nњ2.o-[y<* LLr|9 q#(r.rpA.XӼo\A8߿>Wϻ5ȂwLPIik vh]l-2czK,{OnTכ9n4_(a6>&Yn)yS󱠍`ohVx'o\zy(WNʳy4O{Y9"Sv P"vY^䌳V?]X%ruQ ea h{ޑq>=n5ƭ ^y,;]|uK'{?~5@cK$po'@&"k.8=Kr_t5I>[F?$2 G0GݿB2as65/ 草r>Emd%'e ee_z‡ӆ~0"Xhæ Fm!k!0+;c<}<[8QyTβw(xwcoT`8oy.FǙ-S>U}7jMM}]bpvw0?W} NvF; SZ}gڤ`߾=K2}Bſ xr4D#+bDfy B6RZt{#bRˉGpyFQHSק;eUiP!]_M)[ZڭDy%8:R?==?Vw6ߘAj޲:;ӟ0~Q+VJ9ˊaG'-];Ae%k˺bRoGnv~}*>#mB?}+^DS{2b|Q[K.gsa!R !< -wf{y}Lb@cC[v"} 7$< iV%BKaeo6³1 (}mWH~|a_VvJ?]$-pG`'cҋ)jk\hO'a(Z_zNؚ5GSK ]W֙m ٢uqTJ3L?E+юD«˔j}YRl_R˦. >3Zv\N9?G+w㣕8JG>,}cͧoN/w1p(Jv(gݿ@Ȏ.&&hw]lb}6xoF8f1_-!(fe՝3n0*xs_ ~~ 4FGEjoS׉jWG.ھvQ/ {WNafbk7,aZ״moΎcA٬;~14eۙ!B/ Wij,)C;Vn7oE[pptʥ32mCb__@}/%JGȹ=~}6jqT\"e#=6GU@F̩mãzE s|W3[/P*NPH3y X\WMӞ-$~ش{xTG10ؘ}hl]"VZD 8%3A6; _Ħ“2?*fPF3]p lm|虜UE}__ x<̭tMHa%/`sh ?P'gTľSVb+^v֊sr=hJ80 cu89 ;譈hOqf<"8}wp+ ,'2./ə7T)<] ]Si&u%NA<ȹT ':fyk'XrGDC 19V@(ȧ3W+,ތsW.? i> ϖ%Gfg}O;S*x5nGڮʣ'&VgA> 4I#E`5ٓ\$U Z>XcT$R/ݩ#8ВL}n +ads;ڍ[-uzƽv{[1NW67}!9`of9gNPeY@zuCA{*!_+4;)޵~)4ۃ|ԞxfG7.wl,]FH4Z~|7AF S Rf_c K6fU#S `shPYS6pNflu}cKu{#-=LL. 4_%~ *`󔟢Xg}>!ռQ~7BWo[>`=<9K$7hv+Q$ުial뛨7CE^ r:L/.#M&|1^?9xs\^F`_n[SC &/(Y8ṵ̋?W7Nݯ'֙}SR>!:<ow⥃I[TqEgG2nx. x6G%P"t \?ony'^;N-{ q;mʸ):}SчrekkqSҺl|5nZ`[ܢIkrsF{>k/M~c㙞3+Co|&ql?:Hne^u*@[~z|^d/D/ 5:.WҼ0]@ )p[c/-gዖJB/zzY X*Ғ!fS{r7k 4oO^%\F.} W}Lhӷ/=zZ6:[50- gLoa[Rm@n:\η٫gtcHMո\yi{9Wf){ :-‡ ]Rڊc׼7oq{mkۼN̅+>Nvmnwh1*'7Щ2~ćM)-->į˥ۗ޳wXD:]Ň; aDˌ4u8{k0g2hvz1\~ C qBK:<{[6*̫ #c6I8٧0< ګ2լL-!W$Z WH)֌]6Ia@1 fMOxn(f`أc&y:O%AJy4%lg#]d@tiЩ:B3$၄hH 9Ok#r$4fJQY:AgjݭP*}αP9wL>* ZxekԬ*"C;`{եzaE{>4_8d֎4225#qŅ :M#-H[-΄-φL/M-2@P:E=q) 3#xAa~*!Rdm /jCaa2qx!xe v <`x7ZFQרvÃի5^#Ƴlzk 'јӵVlSal}Щ}G `' =6Aoa#|k #:\טeDF2&F?+#.e 5tgog-S>a]􁵖Ow'R&nCsy?z?rpX@N~Waӟ ~ o{-\'N^WS5:(@gc:uFIEA4L1&FiˏDQ×F{&YɈ'o8saOn{].k> !m.hBwdW FlKfx^/4Ѽ)Hn8\XA=5ʤ. ڲGgH<LPM'Q5CǛ[s tQӁy1p$l6^8{l7Kj 8GŔc6 ]dS\Z0u>rS\) 3L8+$]: >* [YǑ4#0WkCҘ dLNJѪL|"eCS帄z@\T=B Mʑ 08i)}DQ%ʠ~k7 {Qx8ar6K PBl4 N ܚ-.f*  W}AJ, |9!mS5+m5A>Zx~n ,ZPA-O6׮7a߽~N(bަA48,7[B)JHs7|$,a'`S+u u6;fp|=%p:Hg = L6S-7T$†8` qTYZ<15PXZ4AꌗSJհl}EST"Uq*Kq\6A!)̕qU(ȧ侨/ BO9^9ft8{M=k!+O̽!TtDV V"E7(d I5qɓFf}=NEh  +U|H*DΰgFk`jN~n(B,ppEDj]$_G)6(ř3r !ߩ;9g q?iBlu p+a&NAx<J_Nw8\lQzxAwItSJXTrK lEBNHngؙ>s9ۇ!y%He5 vmc=Q Gp2bWr<Yr>> +IL+ SMvęma7] 4Γs0WreZoGV8x&7=-<ahK0~U//Ja^e̋Wn4 s!.u{X!'3 렄ym ]`)$+'2Xd ! |̺f؆P]cu)z&Wa5v[,_t82\Ƥ߁uZww *srT׳\-\7;Xt {TCBeۖ;6r=1tۂ6<{nqau oF  nptqtu"mu7fsY gB_ efujYvv\4g Op])vݑN?~f pB(e>H3wa^%`UMi f(sv͍BlYm 62]6HfK4r%#6PO|M6\M_ ^oAVV=m4߀؆5T]gO)W0cl횖to ChŤI 9TmC!`hIǼFQfPIZW) 鰩Di9^0Eep Oi:*l㑢` ڽ/ BJYsϐOME,!.",XjuUrPoXSpO ؂3٨E~qYMu#"VrW39rEi(̢҈D?t(:_5bߟd\&pa6UJ-2JuKTjTL|ek6} =r }S>U(\TGv-X|d*J1ϟLIPO}I^ 9 bk db+a5|drS2٢B&2mNLm5e S=] ^<~H2>)+ %9TH-tj<4s֪z5Иz:Nq@ > z+C:] Nϫ K~PgV)/ۮb$0 ]egfr9}Urg%с#~юS TסD1]t[70L̂^À1ɑ Ę*6I 9æjybb2W%8*>Pi| ߦ 3C)"|+ECNb3pCJP'|BaU #r*M)S@J->ftSZ`Y3%֕N:S%8X?ު?©:V*|P1ឈ:cSx/E98B~ OvSY9yjf]6?*&\ptKtˇrRXzfem,!I~ 9ނaS?r^#0H~4(f p ow}'}eg0:K C_‡"j@M_5^aYh:JH/̱a\y7sxFP_R&gY&Ӊ1ڎ˷ݦ̛8d$QVF1EaQпdÃ̚A/pD$IBԔQWBԹf %i\\I%޸]@>E z٠|K)%[ Im4L{G4@zotn-IYPQ# aOI]i[y?}踔@mJߞHe A+1s[^鉄j͆T{ۃ[9%Bk?KӉkJ`^U|3@$ܩ0n!v蟉kA}#[|Tm۠Zc¹oTmPFJ⢝ϦUtIyƔp P+NV*)z-=˦)"jĢR,!|FO}+< & {&8'z%@rblI;y zgZ>unSvu @3ԅuqxp|;f p2]a<%1+g(I9b> 2BTδi! u(o+Fk a aHi(ү& ?)&C^T RW"*1ED`[h9S夺Cj;3wx*FdC_Pix,LJӯ}7vE:|w 𑋼5mx9E&IPS!`Tc |E^†w3 '2T sU\IW)fƼӢej)Lr 5tU;TuXHZƭdD%kt R=Sj J&E]U32H_?|Q6,{itӧ%%0,(:7l*EYRX?Y*FW3 ϧ2 \|:Ȉזt32]q5Bk6<ҡ=&vف/~\n.60nX ۶vavXsE񊝝0r]C\.ݡ~\O:f_X@Wɟ}o߸1k Dhfc.tt}kqgҳb˕myiV`?v]VKM~ np=vaDؘ뽱9f9e?mxIL!^n1{{˺mǨB49c?7 u_R>Zf0mu;"i_u~#FLvong'vzݸ$Œ7~)v\짿}׀& ÞjW0̍edQjysc]g&bf3'D nu<^7}VOތz#(h?(6`dJ3)z E_3_П_AڪTi9?j.Ϸdj8QYcDgOйXշ{>^;_;kqNQ)`Itg}0\'Myeئ&hðA=vlobS=Y` -{؜L{eu. AC]"Dɉobjs0=6aKkgE o~L cp" a8>|ox+ww d׭~ OcM=}PdX!܉:P]0(M1T?cmBg00>ͦ\!цTi8(|\;e k"F M)vaGN,o1Nir~GL|k}1qrweg FX IQ 4X(@F)?_@Q74R 5N1 yhfAVl*sdfP'20E?* |PD0ozC-AſMעK|`JZO_L^G>`upsXK f)ľzw0 R#@,;7O嬗5o6Y wC;2*bw4)~2k6%讆?j1K`*t [# iiI,xzi\[:e-jbm&BKvVASXO@h.y_hDluw7$gwQi}a ZJkIK ,ڕ|~@ J"XbX YBBsf&3 I71bf9}s- ._,@%-^ *W|dv]u<;q#g!G6sR_ݭ4hѭ.b>4"VZdQa㗠϶i}]XZBAyExAVi[4Tc*l$1ħ=K2*qATi[hKV`%\E+jr M},]#u@hw/Qnȝ-BlfwVMCymEd.,)XP;dw9bGM/gLvqeZeK{ HCJSMmɁ8~4bn%_Cd01lkNI'ZW1.96E ]$Jۣ<63A4'ĝ:{yЛֆ;35S؏>SKe.|Fs3i|LR_KʚTl' ұu{;,E֥sVmB>SwEu2i YQݿՔ]tlq;QRTZHr@>&ZpD>"R3K%HI("NGɰ>< Ϭ3&6-d YK5}hR 讏s?% ٦q=qx'>lw]T '| ,`f%LC:ŝz]APQKE.i2N ɠ(eKBnBqP/8@$}ZA5|o>s>oR=;hD 蜁U!9#3X8k}U*N<lw8<- Y%s.KM 1}$X}Z0Rb],͇i=R5Ov1*.͟J; 2%$D tCT ӈKN Ǚ̦NLL 7V~-~oFprձ}FޞIfXww"5Di"{rgF&rphd둒 h7"I8_%6r|C(~kh8wӞ\θqI@& UN7zmD"qQۏdCv"22Z~ Gn*nN [>0oCAZA1b 1 `fȾFX B|s~/,f%vF6]q;U#]Kip{%hјGyShO}ZhweiPg1s\(Jy=х 8=L$lvs{ -A9̧yUkn[i# $lZq=&g0; h ]i@a@x)C?'Sr{HZNHAACLmIw=-`va6 8+_3iRZ6 ^H9]\ʚq >AR^<o?D7}E#@&2Ŭ⨻BHC"g7\c8~ձJu"S"H:W: H3'Jt%(_M%T=?]eR-(e Ha[+(:GLK%R]5 2]Pn,r\mQSp .~, qce#[0Lfؓ}Ci|* TwR؀y6$bZ  %'KONVςC <^,8JF`#e4d=U#ߙy߃A&Cdid ƝfNکeؐ«QoƨVI>й#V, ԗtu?}VœWܟO}[`ZICB o&bXCf, o>[yZa bg'ڋ=6'%@TLqP9L*TMG>.F &L4]g6,,`C_Ӷ"5-$r|`'#yp'Fe8ڇF>Cmة|;* Qr*]ϧ*s䡈'<ӯJ*nor\d3E6dsn;agjQȼ )|`vB5"AYȖ1Ԅ2$SI0QQiw7{tE2N!|_ؾ=( uXnYHsJN 1oߎٍ"5AԺ?\*4~N"HxAu_-{ @꟡Ln> DŽۿ)eF 2PbKFȎ&8dYY2]hlPĂ3xi(iB PeFzt#' :9GnPBra5r~3lQ R yup#[SD2Za}`, RiWQWd(6Kx gG#vYǧv&yĮ# &V}B E^PuE5[(wlP  I=C78 ,L-],9bR,f3y3zlm9,?E9՚"%a:% ͯ hTlb~No-C^N`6G$:).?G*Xr$#J [1SkT"(SN@x23m!*)d^,X%7r~^LiBf*!gk2^S/N6q:3e8ElME8B%12b2]xJ3֐Q~I?ݟחR9?>KbG<jt[FQ(݄IюlSE ɂM7;j-9b[W|$}Q( \'n?ǻ BZbLP°vՙoxtOْyDKSx󖵌d:9POb@0b9V?V,ͭ\\Vt .ͬL ͒[ چLfy+vg9J td ܴx;ל+rj;7>#,WnF=uNufJEٌ*s[l8 Il@&I@x9-7VaTFߞD!'ʯ }&< `& r$]| *ä.QS8>)dZtݼzP 8ig^])k6' Q)?Oq &IfnX Xn*ג_u jiÞJWS\dH/y<7FJ1+I3&Y6l5"a;e1V>6*uP7Qf[|;0I0v!؋풛`AѼJxQZ0f7Q7!ۄT0E$"Z!@. #on_EGJ|u9'B ,}Lg}+5wOkfi@7Aʋ1bVq6b5C+$^H]baJjP{XaKճCRUqΆMQEjיK;3k#ظ܉6}-Evdc&"`vΜ񼆎B)ԢC}K*T-?7eT調ǏM5Wm"ӕh9 2L)2.x񝜒$c&>gzyGN΃U##T>!4>D>> ?HD@Pc ҆Jd* yNTX,$<q g7JϟEg0#3ykzx6/+a!n1`cv2p)`Hc!L7)/V'96&s*#ߵ>\(_cLfL+Ԥ~T7'd9Z hg,d (POwk65֝0󪙰^fPvI%ag7L+ g6d~h?Q9LN@LAR3)I<.(ϧR8Kt#RB&_-rw _N穪IA.xn@v]7!ț@(&:n emu\6[|b^L'm/?Sj%t,jJܐ ;ųA2#@..yMTYpVB4Tt5Q6 W$n^_ wU="AG 4@aLIg="<ߜ;.ۚI9&,$Vp?BD{|6 e|X><Œ^9zAi &e(Jj|Sh<ãzq߅<>6SczK䆆>it o)OF7xr}&|y)'OD0F>-L[tXޓO}#<7\[SɬQN4{:\m$FnM$3 MacxA:Fؖٶ'z<3xY6vc; iz3KѓQ!'"aB/^}kHhvOX khMRe?xYSsV9Zv"GV3m??"(M%}rqv6xH @D)!X_&uPwd 5Ҟj.AgA)k٫+$5xWFJ9jnrMVh[te9ZU xiD& +oڲ,7+GtD%΀_NO/cUp)+~đ4}~fb0?_$9#cȲI*?aPQa^gD*[œn)9kz!Ijo#&9~`$tD;arD԰~L$lޜ!3 lIb,{ [,ɦ}i1idзd1d2 #۷`?ځhIM7۪7:$.r8#0eNm>G."ԓEUJ5fqgtU_LyҼq=5K30]qy[=>g[K,?7{؟=8y*(z8q@U9QM2kRz ':x7Ob .%/1WH~s%|F$B brK.>t@re`~p `w5 w? u~:+pTH 2e*?gBɀ2JSOȕavm|Z kIBDbA2`~|4tVG.s;GoIa mZuD9CIk-MI(Fd=)--+j^Ҥ8½2{|8gB6d4 Dj|͐L~( @zN؊-,UcJ.C+ d5LM`)7;v|9)vwaB&o"b_k h0p =%`v댞5YMߋpQBF cj*,gך,a{xtaj{{/d϶r&nӲ;Uw<#C|;iZuGE%@>LbA$Fȇ2+u'!/ߝv%y^0òrW7+L\*^(:3N #]/?ऱ%j.+uT3S?&2`n*! Wq \|p}T3,(5xKgj愇\E^{ହm#ziD[s*5A{9-kUp>rCԃkhN%Hײ[\Zd%*FgԔ}ZZ,|Oy)5G1tʚt쓫;Zyw |!XKVd7JKzQG8Işy k}cq3z\\ neaܩN DdEk>$n\J?dsc9X9 _ӊ|d;$AYjJ˒w?v4` md8J3m=6?]$YhawWj8164@3fa&k{1v䷒"u[ƾ| i~28fGj. 7c&b  QڰS ^MgIQϨ!S J8ߝ=\wG^MkSr*8 FtJ@R$Ӿ!$Ϧ&0I{%م.G嗦\s b&_-ba3<ȜǷHlxThvAPv^a*_~hO ?.ʸq\ ϋd}쒉+̙x·Q)>$[!Bi6ޑ=A?cg֊|s}Њd~.rr8ʥQ#vKeybFrh&AT"Gba,+!mS%%o["4g7V{B^֙@뀠_(0LVʂ؝h7J @@C6b;2bS,DT Sf@%0u/R-Vi΁Xd&>Mܧ ;cdSTW'_]g0!NeN *< gk)vǬSvݷf#l(J3lVSCjpb>+O@a.6Xa::gL#\`v."CYkˍ>7GpOz-rC V+}| pf~ ѷ4]F%G lzK=y`Iq 0^Yg1{mćۖ|9 Af0t_MH_d~ۛ-JM.t5Ժky H]*d0L2E?Wn>q>h3@d`1̕9-޿[uEqsIB,Bgx:IًZDJ0#U8o&ӯ,=Х ,s6,6i$kKԉ< 䨐'ZtMmQ]}:9q6F ]Z<+ A.DG(t_\ ?ͨK1tj6 7gmrwK+mF8CQ~o|&9.+_?'~AGxf߮}'h9ȁkAߴW q8ʙvN;T@õĹL\ÿ-tq qf%jR4onm ?KR:QG·3Kl)%.9÷:P8)/-GSݬ>s&=y6rS TRۊ6֧־&6p8j៉uo׬./EX =d-!WAN ZH3 l(<Dߏ*{T]{K˞RN.^9%ifiBA:a3Ys psW)m?HCdSkk5nԿJu,`53l, 2جk9ԈwCyehKu cSlThJ6/P/pa\+ZJGukX2Ȇqں;ˤrb NDʸ?كBk/Y>VF%ќ*o,~GmwW\qSOcPeƎ3oxѵS">]` MC/Oqgum%@x޼ e엷]$4T~x]$Ry4HF~3iW"AN Clƛ ^/e4{^#J~ Gt6J?11UcLiاa" wS7r::''iDQ*.`8h5Yމӡ)7ᳱ io oOsC{WcROf7sewY!T| qWO8b 8\È2IU+Ѿtɮsט; H֭rdpF6ƽʨDp/fUw;/S{Ǐ(\\[?s_"c%>!:qCx[WČL N$Em P`ωYKz,x> }AQ"[J B]k2| ضP;z@|*rH :@@-e*NID,r+gtUd=:\aoh^&˟esϑBp9 d)G"}Գ%O*5_?8?Cli)mq+ӐE‚Fat)a[sQ-5po/UHd֦}y\nB=^1A=-) Yo qlu$35T=3Pԧn^'yx9M ujRCG W-~?9F/@FŃ%iu׼ρբZæ쥓'w6>kKliշi GCq?%!a&)!X:y4B T|1z;i^-'ŕQ;n+i\mP +DNk,BAm1YsO{䍝 ̣"D_n͝+.4p̙]Wؾ${wDӸUoTT/=8O)Rԑ;C$9rƳA|*xRmٖ4j.tR \(aAqps jA/ ׇĎuqJܰO?3,s O!MIWpݨ>k/ˀYB :,>ogzʡYO_KֲOuVN=TJ٧@7+"UaoT;ޗ Ŗ.LQroL }V8{~2 A <q.uFȣ,=;A$3k>~M/9ɧ i MLe\+Zgj>=.ppB1r1^ !:d.7nw.exUQQ"9cb2 5G)ĠH9 8_VlTl)өh蟠A bZG9vӅ<'k 2/ 3oŤ=0W$x _>Ҽ%ة SNg8tG9I/ytvEՠ6:97mX ʯ{NcGC@h{t#p.\e Og0.IT_^pbyij4A_g{0hmH̼Y.0Xl,zr qݥfƢ0t$Nrc 5&'qdPv?ͣ$d/5!yUs,,Wϯby>L`<ܓ.C:gBcD/> " 3P7!e@qXK$PF.HivW [`B w>sqA\z*rlVȱaf2=G5wҿsB_@Wqr9Mv'܂V^ D_(Q܃5|q KID\o +g^hQ7sr^S}),#k(s3%(`Dօ,|[Ux|ZxxeYbtҧ|t!r1B\z`mx*&Ɩ6J jvJŗN# M_M87:% ;ZQp*]HP=%tgj&1z'S:l+T1nHvp|/p0%\wYm}XNPAPb0XuC&8i?MٹdcJ]HTS%[0B[*8.EH 4}n5.P gpł-v9Q8'E'W< Oegi-[>\trdēq&2lrj?21Ļ~1;E';ُW%iw'y! {dYejkv>å,Zx~/i_;| jf~ mR&IϯbKq4Lb2l_O BXNp ~{>2np Mśq)|c6^z4D])Ó))GbF8ޔ42jhV>H+xbH; ɫD9ULd)pp8Vu|:tުX)aB#XL8CQ:L2SzG\dꑌlZ-@8u|ra8O.1B~-)DFT>\=dY{^y6+AL.|jEɌEYOCܔ DϯN_qo:T }yۚ z T[KYDO5ϸW2Tew04(p³_5v>zⰣ$>tځ,>~ȸ7ẗj.0BD0ReBWnqaeQ} ,Kkݸ={/f`V4̈ YE( L;Z;yahբDWͿrt5UoU6= +N XtLPl(A 2}]..R!ڨxq%8Є֒Z4N*n_@q Zeb1\kX;+b#æRv{洔ɼ؅4ͯ4z~5tsZY|]?<7` 4`TWs2g3uW>IcI`Jkpᄈ o ۝RWEB3ءީD lkw4h OHP>Rp)]7*sXMJ -=blO'8$9/%_=?~z`0nYJ" pN8)O4SztJʼknz&lgze9a?&YyB0iC0@,zp N VK3 4*݆AEIWʊp jyS]Aa$Xr:+[qA},zz.gR\3=!D\b^%G#Ac8bhB8$d8"h9?!.a^>al.0`% 3džNGx֕ `,hFoYzq; F6?eX=,5 D/{Ԛ,Nvd+f"I_+덺jQd?z%[z f #noC.HЅ'qDqgٯAݼ̼mPDax蠂!L22Oߜy)UtVjqo1 5g|VU0K1$hlĨ]y<~z,7Ә^!0I<ۉoTs`!'@y /xM>Ԝh=LQ}XJf ާ.X#L,M8PNÑ|Yc%rxKۉAyV?lK+A'ZKNѻ׾fe4ݺ/_OK+?&7ppT];χ}^)~uȒq5m>s_ ag"HE[[yBl{K55x}=Y|>(PJ s,Ծ79ppp|N;tpbh߽qpjUF`Tld%#5[]"[g.]8g(07.X\;dbܿ "nOQ; „wCYHq1VvOjL¯~ m%TgҺԔU#L 7 Mns<ӛ#U`c0(cOݮԥ?05P8Oݛ?R2q$FE֙2l@.U`6HBފ?9˒DH͐hiTvᲲYG]i[J~g~D EFGGG\QG^ ,0%60ݵtթT&вOUE[q(>Y f(YDqn*MSI Ȳ?;Lgkt굀Fc_T cj}mpF(&%eV$_>S$]/u oa^<2t%F0H m@5Z+ N]uV-xFpI%K $dό"`7q<܃lҗHCs=-۠7jTye w*VfQ*!ǐ J|5"kz21SNۼ]%K`r+ b%3:[733T/IX+jC䵿ǯayΙ/̕CMzƌ hpORT~EhYh0wZ^'ā/w"vޤZ-a\2 ORL|HdQN+QƑ(NT}ڰiwVR*tBieV%Lߦ+߇m󡿻8>AUVҰU(r^ Өj^zc8NB`L+#uLëǶNVMpS;KOY3 :>t8"~5pcy!R:2CuF}Z|O<3% F>h$OЙ)vďJCZ+?il:`$ێk?NEOeB>F(BHWz'~<)>|2+(Oϕ i3q4z0~0;T)]|%sϙp$6>YjAtP|f59ݸQ: Srn \FZҋ9˞B|/;ТhF xv:٧LSrB'9)ĝB5|ND/w}_;-m,O5<^ęGqkY %R؃(تa7ownP`^]ܧv  ٖq1+վ~.w㗝TYB'LagUn;S:8)`'+=uVOz(2轖Chex{ _.qlᵝoMbZZ䟑FBݳf6ݝ4 vh[nWy0e"hdOٳź`od'%qU28"y%C"?k1ƽY+o& \1"vgߢ3dyGS}r7b#lՍx` glLOSB;E:yNXb:$B-ɶP7Cvu`&|?\knLŲ$b <5a,.|/Aa)GB)4aa^Ȩ,wFl@F(#dPOy+!*'b>Ơ9QtQo ch~r@R?{llFD1i\ҤJļ@ ޸}J6τuCHЎ廔~G1IմI S,8L,W UPD3`Liw"W جCkbS/f8C?ɿ@ވI`)(VRpoL'߼3eKb,dfĜ7~sPC R֥8[o[8@N X34x#4C5]rZUZ%sM_ܫ~GyKƅB>IB^0f-ͩ._/;m.,[XmrHkKw^ż=3HR|:Tގ Xjņ"M6`Ϻ!Go pJHED+<8I&S{K-}O%{Ĵ.Q6׈r?vN!V\7iLTu/ԟB8}2?9nƈ8<{ ŜЦˇS8H**>ZTF)ƨ<}67m% 0Z44E\ YuchsH^8}"(bf)5Rm`$+wpFK2ԓy- jz~B$Տ]'˹^bpSIqp8mY+ti{$y2\?Kk?Tye-6L՝(s3{]KdĄ^t+N QCdrD|2ޟT j5Mݢ3ЋG":IDAXDQ^w1,_F>]f9huQ])?͞G&Frr[$SpYw8gë/C8q ŝ20[cœIwNXuQ}G}DԺۈg߆Qx- 0kyԡ BٮQ=[[A\oIZY3yxeymF^B7/n6vǙ-It& ".[HU$U.*:S,nlZo\9 pu?R'fSDO)YB28뫜3 c#nIy9{ѺF:I|g潨Ԫ 9a$K;9Q?~jEV'M2uuE_3-wJ _Z)u |%)}Xd1]072TҰ.=}z-Y1NSҕ9TKm Inza~YcK.*<?b&;.K<ˑX,ɷbI(f'3rF1[p "?gh3цYyTVݩ5=NwifI嬈yƯYhS]ƘO}|j345@ȊPo~Ya/1Lg+۞ =se<HiɤkVԺ |"SޖT.d-Ol;']-3IJΗ@'bHDI|;~!i!:& B랱w}.#kT&Ň @waCrYo# q d.5>"I.Psgo5FLl ]FM,ѰTS!yE=].~d/mdDNF]'EhF/Uqv&}Uh,"NL%Cerr4GCq$u 朑<P766 !Cj{rcsOx2kirQN OQ7@F r:2t1$/lyR9ʝė!ɧ x9] ݎ؈63^&N'yn¸6rekVL.ben/\>䓌rsSJB7PYaUJ*0y~/-?l ~h;('/P+3#La6IX,EOBHk%O˸;|Pu=ENJKcaTbY۶҂:  EK4LҒcI?rɹ@UI<'_FK\iE [R( l73|!N:*Xh6wF+ -AFChqWvG#j6oJ5'g0J8K )7iC78OGSzj|Thܪëvg%LY, 봰Lːl> zEߛhҡɪV-dQ%yts1W?(]x/jb4Q'\gT=d=FIvU~tQ@,XʜɮHga ^Etn@vL\Zڙb ^2Rav\C4x)(4mq![&~-8$Q0K1N!Z:x/EU*g5Ggmp~& |)s+g0gHZB3zƨi97&w.6ڊ={ I>"G+GS~6T?{No%]emVFV=:ZbRjn}VD+x_mziZ *Thr@}gRQp գ207˙C ե > Q):IL'lQdHS$ |][Ɋ;n)LQ{pMESt.o8%8)(Ѷbr7BF 8~n?4zAj{lZj9Sʀm_w˒UkxsX1XXq/-t)}Q.ـ_*&i(_V;'~aA~PB]YW"A}s]PX,(n(.-ﴶ[Z,gOƍ̬*ny"ވZ=J x,f=~%53(_Bc8f[c0ChHoFf2щKfpɊŊ &@7Cӷqw.kH8H(lGwyK/Ux@IQv}o&^♤h TtDww8%7uw<=mD|,C )k YLrRqzxm?GdhjmPX\1CU~!'hLbA1m.46_HyB0k~B )Á{Z~:FXQDյEd,ե {߽.QL  7ݵagċ1Cn3~cӵ7_ZqߜLFJ#𨝉v-qKquhumFwUGuV.G{˘' hgGCFe0p2y.}}EG|B剺jU8 3u$#|FUb\Eh"-xb=H5kDx烔ݟFus(١Bc$y/1\11pƒEQb/fağsǗ=կwN#F{E]oXƒ,EL59PbŘxe(#r@T|Nl8~BCXt레Lzr09H€H$.QVIsu>xceID!S3Y(GOӐ9p(N S1ڞy7Mb:J *֓p< G0{h43c=LO8JXµH)0cC= P6Iw>R5`o˰V,Lh7h2)Զ`k62K6i*zv$\A6J9TjS2d} ƺv=?TY+PsxqLP~, [n/C % F4|^rZYQz^T{hĔf"/V5#ߡ'VͅwO??@ar(kc;a&Jj{(vryiM\55z|Vӄ(;Pn;ٖ6oDəi;#*l&D"kPl*BnnQwxDWng!#LϜD=;*5ȨEcf~bS_r=]q;119ò@ڹV ЭN> ) wϖA;\܌<R1 ,~y BM3S,VXB9gPq$|a(9% +/<&҇*OivvTu;*oa4T$=R!.O~h\”82?OE`4 35N82atN_:Z `סpzxrrTqWB-:QXwcE_o>f[{FvW0lG7R56L-yD]UEp$~"vX#|(+҅o.AL} ]/ "rlH5j**觽 ^H :(_ku⭞`i6D^0m0`1q:l3F~J,9{_:U*[c ZcM/zepr+R㸓X\b_1cC  J'N#\D>I9*9p- =N tA*f1~D95#UD+MDB: HV!20]אeƌ34sjh&+- jFs(Y R\(B%t-V玜9Mi~_ 2e Z* A@7Gu{,6l~4:x|d>FCL  p{JC)w3v`f)Xsۛ܁+FN  DnM4䲌qId3]nJ xrVOȚf4iר4$5M^ҽި7olQ7Mgmxƺ {472<,44e`G- Km9:ҙz/|d5Ţ9C,/卽N?큺|#ucE/We_l]C+ .=72$@|EGĀ"UzpރPnp>f"F׺ ߍl?#!bo>z{Xw}H~%qU.&Qd4 3hgnsFMbF5@\DO1je*y"ӷspS߉1V=}U'i^^wz,y)y:@,<۸p?= dvf'3:*_K!.8¤g#tI;ÒPhJ'4)՚|u':\R7'ul/]rUZ?F>xe5zeW.b-t F "MfkPZ :Lb/=P2RtAd" ʛW6:\)@5Ywim~$)sDd $FA-b %h=lےi iGIW3.[8҆p~w^ԗݍeXL'&i:,p2BޖgD,w_5jGkgX3^D Zw9-:`w3D !(629jqp\gND?meɓ}v~~Li,#P3 ˵IZOd4^ QLhڬ복G^XP%|yEwC7~=!VeaI Abt\ *'fQV`GVl$e^URl*?UB,G}cc髏D#3sRWH),12O\ڪ "D(P`kOuCv_mpEQڂ+2ch|H TT5w,UQ\{zr/%~4B 0,"O!1_%]K^bL;"fTphz܄$2=vm*Qk̗_snoW_2a+8Ud>KӦ }_CDT/?T )s,۸hԔ]4uz2r2r0M;w=¾bҡ asY4FjM(. ,l#pztUqּ}N8Ez%B$@&TI#-htq3pE~7-&+pgu#ey3y`$~5U,^, CGxgFQ۴!qvɭQ9?lu JK^Pʊ#hJY%zx%[LX.`i9EpZd8 YuVg8ᗸJBAG2qdW0ΛwP7~l] <7hoN vR_w6{7^tpӸr%;ʓ0ᵇh~+XIrVu8!5y6y GdyYޟ@b^ʁ?7rXIuVTBxi+vkz(-;.w2!pلQbuILhBg'[ ѱhV@Bw__0+nqڎqW|>"ˮx׾ 5(W4/昲1F|nEgZ,=tXyM""W} hd%:"~sǓga&. /0m%`D PQޖ!f;s\/rxB*z%)/vH1mlxRϠi &#$:gqŒ[gL-UfTxb`>/dd>R}N&d}@fgֵm"o FgٲAB, ֧\mߞvJuB1Jm0?:ǖT&-wa<:Wߗsޕw%,9Pn[Ⱦ)-B!.{9'"ش@3g^H*#c_Fe(*"s*+-nG?Z0)9f*9Oժ5x=~UyYsc2ykNQec7g^2ceu{^ ӏٱL :sȋ ici\ФHHD5R9Pu>aл.hx]3PD4TQDCgCSeT@*kUU-iUI.ry%KJ{E5¼$heSTUqrx* †k$eNU øPH7t8AuMt 5 6pS U>t ,H,"x 8&a#j<` GBĆO˴º#}ӹة1=.:N0 5>37SOLzE >dύ:sIE)Пq te;^[lAbxQ^aqJ_9d$ W`΂#IqJD+e?) (9.0ji+) 0W l4nŦ?`mSS@N3` *PgM8&8<ْ%9'ۀMǑD`7ĕYxeh{s!A:t#"̰\ő_Ogǖjdx &bPxA.7lrfPe[Ybx` vzT1!yA5즽 rɩ+5Y'1 q$'leԉ.'P%P3Fi :r* dgaTT^)SS@IvNNPXux,H荋#˰z{UՍ 6N`[KYAaʯG-HS[/cd}*(q /zvJ~.: /Ucc/^=;(*Rzu$]:zFn^'1G]n6WǑaDZ9mkU3a6`F+E8Tk&s 0_&zpWD5`ssF39NtBf\Hiב0%]dUH(xp0ՆTC.shH %ąXr2|k S:_*QV$UӠS }UNJaUEI UuWD a}TjFCeH@EuPb _M_bA EB]2\`WgR BNWUA$Fx ֕*بh5lC] ڨZDwԶ)'F7w4!$Tv"~X^?rG]@r9!M&* wn, E^eYϼB۴lůJZVbUڨxc#fQ2.fٛ-pypx߹be,j+ [-vF"i0/gt"Vmrk”3/,3(hDǢr.-ULR6̸r&[-<Ãbm=Хe 쎾n2Ʌ̱0N pB,n˚Hl:>~wiގy5QzKδ1-6޳m5[wppޝ :n3X^|qŒ;FttՃ=N%VT'2>1!2c?++p6NHoقڭ+S=ƶS~mfmP*Ns8oF~x:=HW!?&Q6B]o24@iNH@Tԛ[L'gېQp-SP\R3hZ1hH6!xJBgM"Yȃc;b'Y?[>EmUi O`I|zT?ӄ˃Ma/5 813[d!e}9bnؗS/=zPb#V'HԸ#Õ?wX:.qgg}%%+WYxo lv<( L @)vc0$r&FwmM۰d EIy SԛxSawJN4Y!P=4AIlL߅ZMn]F~s'E)ϮoQ8I yfOТ=N_ U ÓA:q&(`Cɤͥ#2k$o30F)n? ؓc6j@\{fӤN=N4`_,C(Cs{$2sV~x`m=+'}V4L'>ݤ)pI] 5)]m,| 㥙jȊD[u~MwIw2h&}EiNϦ+,z~T؞G6Nl]UKN ʢ;} D02W~lf$rhYԂiKi֨T̚~*=mAΜ; ܊NYq&o#M%Fx XԦUAF<~^ם y@-񞓂#~SltjK$07-қJ !@J |gp]hENGf1M-=Uzb^|91DTyGm淙!EL_iI^:M  ~7Hhy, -(=4T|7X98;{[`w(GZ p=.< JH M iQDeͭΐEfhb6& q]SY$[/ؖas:y)+tl1̾}34?} OEm|t>ClgePhHvEBzս, K/ ۉYNwݰw\@kZ CӭSq[Ul53 Ū0+[g'>oN?Rh_Ա@c}3f%xa^+ SDM!;_nTE-_[n Tm- R `خ7㗼Yi0BAz~[:4Yٽ1?nu}\iAq"Wu}}jZc}3f[̦+1;.A~+jA@t׳̎YiW،Ǹ:p#&T[jg+U)Y`wYYNAǦt@6]AE5N-h1V"QZBGɗvӮogo.qWIu_xx/I9Zcib"bHaeɑ v6L <)0O2  Y%t8pc`\ݹՖ]R-'ڿ0%,7豌6S &rrH;1ҋ"nщVEI~.mz`A|Ys+l3Gv ֍Jç'F1l/)QEWǿNqcE+j.e KMMQ?[2[\ke-0s9G.a,ص.U몳f8ifsP 0DUTbwPխcV/ o.YWreho/]1㿦l*D$RkN,0O/`qeiQ\؋pjIQW+Tkn%{l?K{NW]sl3<1=ElxR^Yd'ZpB'XRfXP Q7ofifc˯v]>:;^xƘ>]XS snBj8Lk1ø|7of-$ucevY? FU~l p,U7D v;&z\}x tlFM˗ux/:fٺV]zzcNpT[x <܂ n\鞼ۅYӳTMc~Zan?QI#~E龛+bLxŖ},m]D?dxpHL+ٟEfew ]tinFa`z0'6HZ짢=MiM-oה?\!5%h3KzO; R/E`.&C#}M ;뾙OYQG"T6;s&R^/Qez /кJ+ Eڥ.&')}JXך;aƄh R=!ZI֚L r 1ILD,ьITi3\VRMr8g?wZ=Vfˆ@R$2}+ˆ@R/ I$ 9$|E }I IgA@R X9{lTN&vϽo'3`λ{#{g_^D_̀3V%鴖Q@oIf^jKq3O'7g-tn[׬BA;[vw oD8/oW\ŎRx"?|VN2.V{bGGW-块'Vg \,zpDـ|` -_"*\K:c cծ2Oݬ= H.V ڽ3dԿ7WTNh; \;9"ҁ|,#3fIhbCY9a6(Rx/Qi, 6ӗ3ED*L*[!d dg 'wem~g;+ ʮ 'UIilh_7Lݩ$_jR^|f2c(rL9 dڶzKxߢZɯ/*jr )GRD g!gb/]iJQ}Sر.o_,O/M\ˋN;II#;Xir[tG e|5{-8z 0[<5/{t! ƒo{~B޾O#j]kOpF?PY{򕫃MиVdRbeYOdĦ@,2q{d%zfEJ6VO{6#c"45ʪSYy1S;| ;e՞\62NiKDv% %FĔn|3WWA`%x9q{ˈ룻.4D+Lhi+_6QS7ab[九A9m.sT3 /X.!AG;9 N-$QZ TFF$|D`׊0E?h&.><]%L<3KYv.E^ک͵e D~>;Ԝ}G/*^&?8scUV+wBۭ )yjORR[ӓZFX6b V0s C'wGtrbFu<|4(bx&ڗ 5NEFc,MٓqGMEs1Gurrû"X_e}8y;:, ^AB3xryQwdQjBDi_.?9r_NPR^HaJPa2w{aֽ}V<4ZkB!~q*ȳ.rә o$$k8ak4)1[Ėc#z &uĜ"Uu pg1[Ƽ52Gw%Xdb .I S`Ÿ1BC>y^\M?2 L`p.O͕HeaV}ndFnn^m|LY`[ٖ'Z57$Ngytw@N0)9Si,{NQcTb8i{}(kzKGF QZm H=Zyk,>;G yRGcBg?K' Y5YCPVF4dVY>R e48 =]@ wyA*=+LaWIl="ǯ;4,.LGK b h߉64͓h>y*GhNX:Vb4pH>ZӱHbЃqLRSb.O v#aa&3ĨRrW鳄dj`*OwƧn|htbLsSw** mb_P+CX`U0Ւkb~ ei&ZPsZ{^͸3>_qeWN'pINoL PR\l<4ьe@[*:XV&O l0{=uGKM Khϡ%dhMsfHUˑjʐJqtF5M}T,G֐!RgܝbI/ f6M1O.,Td9 vni"pƒbB˞w cP_#@-G OvZ Zq?\I_}~EƬS)K@oN`F`q&l;j6?1MWtA2G;ZunCxU:B8#H9w8Cz=b ˩;7&=yG6 i żCC~?\Lӿ$6_xOYI Bu" SepCaj1 +ƍ8O-"7|. Wrvq +D{Ip E U nsE) ĠO%14^>K CP" OoTHfLEqx $X}r[}C4 Q^˾/(+&rŵ !jCᦷVpO{l6^x M.­0A]3ܶg]K9Χ1\]gҮ'X4?min0A ] 3ې7t/'7t] jxUFևAH.QN)^LS1sS :`ަ5ϴCCI ;ʄ4ռd炆Y+[>Y!ͩld|9 Rx!|Hơe@e+d !띑Tewu3zun2jDj;Ρ!4DXv8T#sGonPK.AK.Ak6/s\dęݕ1{vƚ/u|5ҽ`M m&ϞWQ`ˬgNʾXl'Jn^F i w5Z r=j(d0zO8ڝSbǭk,㖋qK.AK.A <͠d ͠*\ .bnPe'%(``EA!J-j41: 7Ōf ͨ4JR'FNGC,;o7 G$BzHbE#SmʞNzkB4Jcb2D9hY̿!hӚw21(^5%tln$pD|VfHHo\Ik <(bxC:;n32(rU6Rf V?%&W?iʎBn&M](?fߡCzvCAS!xvl^hgs i՝a=g~w?^-~-#Kͷe>Oj;^!_?̠\NWfl_dR-pҔ%h]v %h]M`dS^r~LNExz9.Im0]·ׄb9inQQHzS;Gs959( ]9Ǘ/7duAA]v %h] ^i41L*z:/(rM;q^;'+θ"h>51rLfyl ̀N"t=$22QpČcckdnE]gtS!cˢs sm=˟HS=^b}q~/XMZɱuL({OҤ"Q~|BP駺K š~ {ro Y߃*ݼ}Qk4U/)Gu͋t^$[`5'f$Hlr:GA}\Eޞn DL=]IzʽKol󀌒|_ ,ę< VfKz[[n?_+p؁pCCWH?M`gEV\)> NL C^ِ@J 6AYdRA9T8!P ٤64ly/oOgPf|"\.=kΑ/hC .[8UMtㄡo1gC) Q|J9N7uHK3 6oUkզ_NuC@򄓍 R.ox žl8"RC|Jj+I~"ԆL[R1s~|AF3r&TA9\7}5V,!c!]&*`f>XXtivSh/{WޔȲ7P+ Ţ  "" R ݘsɬx1m&d֩ΖUR,@ЪYFuhV8Ӵ;<hjr1Ax3}OW+ᢨLpV bu,!g\xdtN)啈m.a[s2T')ۇ\+'xdUr{-t63KVfŎ،chARW b2A_K 7+pJX_ohAIy45!,_4}c["akfТM=6ų$\8-gs[_”_(j|Y&D*hyLY! q%LY!jj(8Qje {!P"RNj"A^qu=͌W1.etƪNV'f޹Ψ+ )EkASGN)kbΦmPKCҌ46*S9ЦΆns5@hբY?gU|j2b:IV=nKz9S#frTծUۋBLNb>`C}",met'zb0Nle=`e̜-k8c qc=@~X3>]j%1Gt9Cc!"铐mLAE$T!1 bJ4SǷ}bkf$E2l5t!yp%4g+1E,)7+ L)$”adU}o`X;["P`2S*owVC3[̔+K-Ԝk1KJ/25 S͸R8}Ggx;"-c[c 5l|Ko77+tl,~o?$/dg?7ٟMutg;Yy?Cg;{;^~~ t%\k'Wfc=ζ\G;5?Bw2X0bHƱy~z8aM}]Lm7~D5Mbț3Ycgf j@]WWQqx@a3HSW{PRr{`|n4P Rm)HbJ<-ҷ:|qɎ|TnúF%>(T^ 4mDEgVk(@&mQnY1g9HVۊ5h]ȋcY"Zӆv [CmwI3oQ6^2:0?PN;Hn(2n@V#d7U<[8M4z&ji3?t2t&X`iD>|gɎ^s1#H@MgA8&#xT43e!͓+-`=UyL`8oF6xUI Xy zC*~|R(sGĬ /6>f7=C>^).d T L{Ƿ(Ns'F{grV@~G9|IVQ3]QYe#h4i4-u5XJN 1=7fe3W 2^tDR69S;B+ɼU)}N~~j &Cfa6QE]˳@mt\G#רM{Sr4PFe9]a#rY%,l83z= / \~ gdBXiHP*p}w^/VBBa1TVk ]NV_1:l)ҙxn pL:%XTUٽb!ݎZ)]0.$S籉R b4HPZ3Pw^&(R'R:5htA73K/Օt۽Hꧠju]p"늷%P us `\S"?|aYOѠG5, bZlˁm|7e]>ju%&\_* eW 3_bK5Hq6u45Cȓ0g Web, 9&5ވǡ&[54jFGy<;^\)p,w֛U2_R W1OU2,ƣ 91-)1ZMV#~ cXyw$^_58> EJ; 47{8џvEj#qQw-< 3^fjTt.J4 K:o}0,AZd9K+EV^7djZU~o)a A~0H^ߕ{φMqƨ=a]PpnLM&T^JIb J yz\ຄ4pHc}ϸ3=ʈ'cy0C^ ԓIqQVAzTZv22őd&O$1zx3*Aj<E_C;= 4.FʐRWX}Rңy㳷eKe)6ﵡ0K[Qj1CH#^SaG|^D$1gu5|RoFFmu &@عh@8ЦH^@*WﱉVNkQLĈD+wz]T瘅Hn TV:LcԘF#E ܑwfO9?6x98x=|wi(ν{uyQ,h ρʹNqؠ<@Kv*Яڿ¸1k[[,|z"}-SX_Z)?WForf$/O+bo2.7X?F&Ћh 7<{]6թ7rWA G}'Z!x2 GB6Y_5#^hE:85?na I[)7rs\÷!4&j\.}.aum|wh8Z(.s,W}B {@uu".Kq7(_%;"pI;_0Rx}-]W_p؋<@$q]8| .?*Ev "?u GK.V\⊨ HHXi@ 3 t=G(p pFPb, z@~ЇK qx&/u`s~? Xq 5pvuM a8^x/H7 D./ǀ(,#*!H7/!!GQqt|BHa``MC(?0Ʀap# ;-ImT?8x n%P?B4'\#_<.DɬB |zಿ\38ԕfߕX{<*#`Ow b:Wvlv^{eAMӎM(V-*ޒd˦?˞5cw:t9O}T[O6ru_<ץQ˦-8k K' *{렖~-j}S3X@n'i׽kcvP+MT#eݓZ(ݩi zXsT`Q-6:/hw ղ 9Y,Dl _[%fuwXL-V4_kT S!)=~T栍> @](U.n4#eoūLxCc̼8`I ۊ9A_`QnQGjZDF8@9N%HS } `=TxD5pgǥ; 9P(>x!%,XNﵓ\ n/O wI݅Q:!{oRyN@8ct2).Xq% =+関Zw3+(Xf 8s@qm ::D():m";6z mDZ(ܥȲŮfSjѼ2s9z| #dr6rts)Yl]gWmGdځ61@PގA9؅ӾY| Xڲ"5E WJo6{Zٍŀkt%Y,SQ9 y`Xc-eG -;|ӱ)o5R?%B U(ޞgg~c:ےgw`/`AET.EEHWD̦nz}<#IfgΩ;I6-%~ |'Qo̐?ui3%GXBP'Jf<$iv{6{txQE,g*5$Vw߳(F{*^l$wz|߽ ew.ĒBx,15y5q2\&f(wٺ ox-fTuw3lMN./%'Iy߈j֜~N/@8QΞ|JԑL-E'UlѽB#^{+E r6#O;;l!Q'_@L=NCwİPdt۬pwLbYh$+6X^LJUH+/RtN(?, ?턎T /R_>w&3K:d]khw!ՙ`apAA2Lu. jsZX]q3!$fZӺ2U7ݙ4$* 6Ui^,]B`"@R|-X*mGZʣ"GgCFW:zdj^Ê׸Kew *G-:HŦ"VImݝ*5q.Z]/RZsS,jcU%saq|4s:SO-`aE6H+n@b$]Mdt 11 1 e9Z龥`Tm.E @Kq1 ^\ė&Jz EڵO_dC#.? qw?Yd |g4C;=l}}"ZF_ htvշ4ݔ}UQ'":O O^]OW3*0~/kX(zi׀'[*.i]eN.wn3z@>-ZhFaWקbئԕ|a\"&,nY%;frO_^ZE||al3r^Q+]'Pw *EIH˶tIH4fԺ"730v5Tӡ뻘ڇIbQ. :Y5u(6Q3z$"L̝4/Կc #4C*uBl3%S I4U  D. )V00MI'O8JXA2e^C =o|\f`mX*f̞6dO+0P\0V &!#ί,@żTmjʀ i33-⛵2oTE hyac 䜩9]`)g3Y\Z<Č1KTIkߵnm3ABCf'="/MVW~Z3[J"eN[qzʞ|UwsxÑ5C<E7D`C\y V왶3-4Gj*t]L<ꊴPϪ 0yЂԟTM_};="+V5W(VW(+!6x1GԷC[֟l?뻨x%*R gUg]|qrn)x&Z<(lb`aD|+fPl0̀r>u,E701@`f<f!uƗid0Z2 qo[:ĴR4oTn[ʗl*R/;8 iʿ,YR#I9ɢ{ࠦl5p '$V %q"oMC'RS״.{4kZ)L-pz%#Xpcӝ8Nm.3N4g<ݱ i8N4gy&l8#Ӱ 9pgo&l?s0_ p d~ӝe;s|8ɤKglҥij8).8V5pbZpLu,Ni'R-?"$Kx%5XE|Wvd^7w3=~NnMEzoڟ[:Ȣ|kik5j+P(^g^y3ϼ?g^y`````XK^c?dT(Da^Mjm`)-)mߴL[C-wr %uzδ9m_v:LĿk ާ>nCG7]$&5]%H+O>O&- p1!Q-7z{&wQ ٯf豜 F "rfA-)H9I$FzdᩌmN6DX f Օa%]WAS?]pA 6e>f[3C$&AIh8}zLLNV?J:kXJ<5Yug{fRf'OMhDL0ZTmk ^hDB4AYVW$RBΤW3H4R ʾo  FC0C~LGpbQ ߂ݬ&*W -(DbE 앎u`&+u(?O݌UO[gjG<@[m q:/H@YY6:XIMщũY{Pxq;OBXp8}>Fp!B}!pꇏ͍ܿ33^JXNT_͉U":M9KOb aw|gHn.˪>=7n>Ol=b~7gĽoUD ͝.ݐ+FܫhVB{`8Yo]VWD"!#FOά;w½lUpz9u_hێçci,H@9cɒ\g`ԯḴ2Ƅtab~]b6T#8.^cbI`E ~U.0o:aDӝU9RF%wrcb1V)*x̶ĀgۚRm^*KVWt|_ÝߵgHcL"I\v ~،l^OR3΁X?4{4gn`zGcrsQOO?;ga|4 ,U7 {b &Y_NEyd3R &MH|)8z)_)P'G@| ]yKV؃`AZ\㌜=r %.RlD2QT$Z`E~1=ٻHĈu FP ?\ >%O{Ņ>1lvVO3IٷS .ZI;bDCT u=wIx ",9oN,n3Hu,KrX |> 13tX{ g͌@t)?hK]Y$,J3近0yG}r!{}W^^- akL wT W5Yn?`fCl}݁ݧIBx煁\ΒkI y\;\f\':^߄@Pq2Ί_7٠WsiA'=Gwٷ1 8bcgN >H $<$lJ/LyyJHG~8]( ?eژ yp&5Lɝ:#64K7J:R[=jP|Hd uI=\`!JGWW 6@.͵H9PoȐ~Y&$D.6QQ,i`j{=0,QlC`~rhFŤL=4OreVqz>Wm1+%.V!CC# -_#{і96mх3stI`1Ekc) 19yyȅ t)'1U)TG5`(#x fU=ϒ?-!~f089IYjWmz&aSOi,.<ɦ!Mly4ê(ԕF.ZJʞ$ ,}HuTp% @b8 ERP5Tx4G+#A ;2'+5a~0"O 5YM߭c߷`I ;R 2[Jintv9RB5zVfzB#K7`y;p McNaw$r&~ m:G9]'$An\0:]M8(YzWԄY$Q.r8N:+GC2 纠bqs3Hohq[8A( ˝aoNwK|!FC'rgspxkElS~c(Wy7=1+>2c<@}})u⓵/ΗC8l\}d2 A=ы9>!KS>(cr.OSXc]9{G+6-^>SB<) w7:(#O oq\}1vNWllEd0gmy.ӻ)}ߟ6B\1NH;ES f=aͪP51ӭ !*6iyGѐ^>vI\36iuGj vhӌ[.~O 7{C ٛ<֨ʃLܱcUb6+\6こ!OCf@A~ZGFvAkPVW1[PE I $wa( &F$yd0q牮cclB1m@@-Uk'I`Hju'A1 q|cA!OcYѦALwlHKQA\g]Eѷ%CHC֊unj4M,y_N(P{(pli_T뷗\ MHƬW7lc9g5RB:EζrW7QyCZ?FG$Er&|}y7te%֟' Q@ V hC71;7;m]}tR4K*;:jjDfLz&r]/ݝ6B׏' d4?vgp' xtZ7|%Kgm@ T;tuYS`NcG]sa9ywޞo@WZ`\ަvG|QU nڟC 0o,l ?4Ocࠐ7vf|>6l*>yc$>Vlm@vtC5jG`|? '3,/wyTFSUL3݃~i짱?ԘIAge1eHV- DO0;y /0JVټeۮpM *IZyplKBŰ`}:R*oydKυaiZ5οGZW~+MjP8ES}Mcy-Ypllm[>2츒G^['I4~yiXk[ enPRKQ?P&1G [AI0P._`i'Šϩ"ʚy-HclgR@l/.W ; 8ysj,YLƼ8XTJTcݩx7r5 p{"4FK]a 8,d0fC0Ym1:\NmJ5hilO<&jDMCbM67={ ^[q#%?J[Lh^Z-wCt/L̺ uZ-:-%Nv95yFٲd: jr!_}ze 8gl䰃i9[ i8f*`,`|'XilqP'Xr^230 Ho0hcuy8P8{Q]3ݢB *].Rt C״Z jIuyt;;}[= e<&uDEodjh/s3E<*"!(r `KD"y{*5u[>n/nyuZ.P Hcލaѳ87WBX{P(texs՝O7b|{~vZKX7vt18.BDi˒pi˒geIZP}Rӌ2mdzǑ~+?h6ܽ;9,҉9FO瑕箻7qmQםYۿf@3|6=|[*L;AqŒBp[o{*Љ qoi@)gvi jO:ƩQWVQ \7F*g0h XqسZR0UKFzaF7DQjLqDoTDa cJ("-@1e(;`ŜG*zhSwiY 5 9$,ή:^dj;ɀR1-,㸚d2<\#(r#=_|Zz˅rqDz&${-/ !GԠhg8rFb 0>#0#;umGL][9I8!C$踀8ʸ7V{;tb{tIJP KhХ`3TfR Tn`%xmͫB!C)2ٳ3BPLtD= ;C)"c; 5R-2vܶUʣsFq3D:&`:`=)M(fs38|zHϧ'x"䋜%,(Ҧ%$U$^fH6HmIUc^;m4ibgil6B[ކ*Ͻh`D>I*Қo $rbSOGSrnLDMӂdB9/{0\G({= IZXOXQkqOQ~|Z)evv o'򭰏U(o2|y쨗dAaHcTo/:b))^PM}i dζV6H1^^@)(h+n|鸒xN_C-f#3# nh('Ux_;]Ud2,@7w+Iݹ\N"3v`o߯}#Տw%cvyfkQ :;FCX> 2S6&u#s%[fS^.i17D k8 #q7T$7(dsH:lŒi2l#!IY9q]GsB6>9 s99 HK^0u(DF&s8 6蚌E7sɈ;#k2Z^r?rHFM zc%% 6}㚌{ ?$#vMFR ,Ɉ:%Ɯlxtkq1mxnm:$2d$#ґe{MFj~c:R<ə$)dTq2i:R<Ywtd$=4޺5QY쥮;?$mYUWj;4۸+1^ɤPWfԌ4W1Y3ĊHX(+.2Rsb? Zb=1YQ.ő2Z)sH۠])@)֍ɬwvNrw)_C ߹3lݕlxkºґӐ0ܮ̃^Z1b$bFAnKEXޞD8-,gM{y.=ӔSLl1^~bpM"UZ?wRaduCH-™i,ώ//1+U9B9aZҬ6]q֘r`5 ؟p8rbPa'0;jw=Gqk|& 񙠊4$ϒWBjwv'N'%Iw13Nl̜Nׄ;bᝈo!"T$,`2gsaX ENj5K;{Cv٘6@3^ R4`a_ԎϲRbx ǮcYc #E aA]кAZ_i)eW0Syq4/dm'X1fajm̪٭p9Lctܪf\)Y\ e>m #yHqZ+ZDʿb''l hm#a3VErKnV*f1Ki/Wc'g(w'8WWB|z[\]1[q<2GWDܕgܿV=;k?Z WU@PV!*@A9]w=k&=={.y~O‰]b+a`ܡ eH"p`9as(/i=M AI f[E" *]|Ddz^DYD7b,ƸDd&ĒH= /"A1K"2ɇ&?W3hm+"SZD^ɨ *"cڸOQB"MF"%}C|QDy1|p<6>F؟bLIφQD$>bW%"ьy\TKBk7c"2y="#"E"z1cQDdj(YD^Nς74!􌛊Ehǯ?H|6Guiᄐsj_ ;ZG`_Y(6ƍ4l<~6_z8qpB3O-'֎v79S+,3'mbOA(zs?f~%H{Nȳ_yW`۞f]/6v~mC)0<~-XjvgO_tf,׌K3滑[vGSz\}yhakj EƷ*#e_AO~s#w!_U (v`IFc>R}QBXWz'0t1퐰F[XB?1}y&,a U=Vc=a M#Nr0.(ֈL/<`Tʋ<&R夙_>HDc^i֞s""m'"B;C2EDpnwDY=K<"2}VD6 x,´ƣ"ȫ=("|nMD\WDmvx7L8D$Pl"|u,PD/BH oНGD"d(W3O$r"66FDX%hJ(DwѳqcT3Fh5 ZEhLAϼ[h*UDV"ZEzVD"ZEh*U.cV\VE*UDTdDDNE ZEKEg"h]D"ZEOEmDV]O"Z DVS뙝B."V"Z"#"hu(*U^*2}=D"h*U~*m#ZEx*hj ZEhL^UvAh*?DFVR ZeDVSh*US)DfJ_m8oFۡpTØxo9 1="׳Al|ݙͬWg<;Qe6gX(OH1@7 cl(yfmy|ɢ_ h _=f2؎[ l+0؎D%^‚7Ɵ\WMqXW_f_}g1p,Qb1(_'PX~މD46Ŷy*[Ma 9P266± ?4.`%17n3UkCWy;wmw+yQ .z{Uϐm{]DG-"?j=̻WDDTdz)"VE*UDT$0Fh;T *`Ah*?)D"h*U~*2""V'""Z"3NA."V"Z"6UD.މRVUDVN!ZeDVSA:ah*/qUvAh*? "ZuNS..ol*L1SFEL6hx|ϔfC2">ŀVY,oo0eİ7wD{. *(zوk /m&}j 7y%= !"z "Ze2&"$Q&BJ^WD$$"{虛YNH."~j5[D$QDxcrz˶#= ]Dt~fW%"yc(_D&gTdDD?EED"ZEhMDV3h*UDV__"Ze_V"Z"VDV} *UDSFVPV"ZEh*UD|"huzhjhѪ1D,"h]D"Z 3DGVPV"ZEh*UD|"huzhjhѪ1D,"h]D"Z 3DGVPV"ZEh*UD|"huzhj*B~6]~4$I\TyN}w¡f nwpĘm@L{!_U[<[/[/v$u^:>Z㙑Vca1iRkf=IE06n FJJUe1Z^)K_Ƽ̮moUR7հ3% X4'O C̔cҺ J<f 1e1NZƙ4*2ii4*gpMGQڱ1{i 1b6 tߖ*W4Uޭ0SjR?: oD2 PwD[_3 ];WֱM{%tʞXO^չncs >>\gݥUC]Y~T/fC6n/h`9Jo %{?n)->{[ճr'ToOS`Lڮcz?3D,3'.~L 5+:ء>i, 8=hk<0$N8;VCi-VH)l\eYz(mnRhVTTDI#ϳi:\ⰋAxp*]w%cF˷jN4AR$tZsl"3_]Z ҽ ~O Qͅá;8Pve0oPvùMP{.+dE6]-{cw= = NMUR>A'oy !nC/w2qGك)cX162xb.LOIWP͏$&fv3W掊.tLq%伹ζ*i8>:[$ĨY' u܅EM=CG?U|lw`5-tbsv|`G:aDՕl*,ayu&E/d$-^olK{nVk?ʅruK}#+K-Z&dΜRG3닋g6H$3##JofKfA9Ȳp,|S#=P 9|)eUywݾ1.C.8!ןsD-ټnQ*p~Ӭ Wnoݔ ! Cotd*'ZG7q,'=(CٵjVk*̆Ќ hr fiNPgg>vͦC #6@|ߺ^}Ѯtkz.S.$܂Yȡ^{u<m?ISEQHBA2;z p6.zAJyR@zc_ͺ]?;N߭uan6wLkJ5j},Rz#< 7wDx+ Ɵ[O}Xw= MP^} 8uwIU&Ͷ7ڃN5C `(l90KLF=(KM7BuK]@zH#YkKشAqzu'[%gwKr(by,qGϸ[O2^k@+5Fs^̻vs0 ո Y.j.fĎ<U,0 ϫppE牘 5E`ZCCgoljPZGńQ ,ǝT9!w6M7'򺯱,fvh=R2:5^MUG{ō (5Er=T]uGMif? B)e.X\pe0N|pCJ?P5 tF%~nV >Bә3JiWS}xd+(ޢf&X:  mCB&{$xPoa+!.1fn_9KxC+r#QqA3<@'Qг"kh1y<2K?wH*<@l1^C,s2“Pj- (aˇ!WU/걶88]Z }4SbI&k) 7wX r^ 'Qj:ف9L jH?79H0p[04 !!0+M q_}޷8EPm cu 3>#wqF6)‘hyR&;r+:8=+62K wR'2UYvOkvqtٵ?H7~/w+CFS"K0ۘe~n9CG^NMܞ2ԙ;(tHE;R5*nAӃ(ǸX?@<]G3SjTą#|$? è^LWV쒙dđ.Q:rnjЉvӐn<>O^w$WTjVmxJ1(M&2\nT#irhYM:ZgkɡT !!c? a04Tm6 O>1 s>,BAf,@vΝr魜 㾦EyD=W|U;J馳'evB~^9ujA`1>JɅYLiz@84Û8ݛׯ[~4[9e92=T NT܋pIr vbaom׵&~w~1/OD ]cfK[車hV>Jb[XK[k\/AA?7#gCΉ5:H2 n}WQ4n ol)D;$otlJ:3a}W'> 3xED;|. EyO(wߝӉwn0Y{~0]ptپ)o6ϻ=v]{8Z3_'lwç/~hT ./-v×͹u^:`?WX_pvqiu៲ ܜs}9eYdQZ/[v- j̋/ZV/Yteً￾hٝb4ዸ2-ky˛Cůjxl5Ȯ 뱡_]܇k9v@޵,s=xI7̣h_