iozone3_263/src/current/Changes.txt000044400626570001775000002721731041702132700203220ustar00cappsrsnperf00000000000000V1.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. iozone3_263/src/current/iozone.c000044400626570001775000020231101041702132600176420ustar00cappsrsnperf00000000000000/************************************************************************/ /* 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 (HP) capps@rsn.hp.com */ /* Isom Crawford (HP) isom@rsn.hp.com */ /* Kirby Collins (HP) kcollins@rsn.hp.com */ /* Al Slater (HP) aslater@jocko.bri.hp.com */ /* Mark Kelly (HP) mkelly@rsn.hp.com */ /* */ /* 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. */ /* */ /* */ /************************************************************************/ /************************************************************************/ /* 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.263 $" #if defined(linux) #define _GNU_SOURCE #endif /* Include for Cygnus development environment for Windows */ #if defined (Windows) #include int errno; #else #if defined(linux) #include #else extern int errno; /* imported for errors */ extern int h_errno; /* imported for errors */ #endif #endif #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 #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(); void record_command_line(); #if !defined(linux) int wait(); #endif int fsync(); void srand48(); long lrand48(); void create_list(); void Poll(); void print_header(); void Kill(); long long l_min(); long long l_max(); long long mythread_create(); #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]", " ", " -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", " -+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 " -+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.", "" }; 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 (Hewlett Packard) capps@iozone.org", " ", ""}; /****************************************************************** INCLUDE FILES (system-dependent) ******************************************************************/ #include #include #include #include #include #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__APPLE__) #include #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #include #include #endif #if defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) #ifndef O_SYNC #define O_SYNC 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 #include #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 #ifndef solaris #ifndef off64_t #ifndef _OFF64_T #ifndef __AIX__ #ifndef __off64_t_defined #ifndef SCO_Unixware_gcc #ifndef UWIN typedef long long off64_t; #endif #endif #endif #endif #endif #endif #endif #ifdef __AIX__ #include #endif #ifdef VXFS #include #endif #ifdef unix #if defined (__APPLE__) || defined(__FreeBSD__) #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 #ifdef bsd4_4 #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 #include #define PVECMAX 16 struct piovec piov[PVECMAX]; #endif #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[128]; char c_client_name[128]; char c_working_dir[256]; char c_path_dir[256]; char c_execute_name[256]; char c_write_traj_filename[256]; char c_read_traj_filename[256]; int c_oflag; int c_unbuffered; int c_noretest; 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_Q_flag; 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_client_number; int c_command; int c_testnum; int c_no_unlink; 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; 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[40]; char c_client_name[128]; char c_working_dir[100]; char c_path_dir[100]; char c_execute_name[100]; char c_write_traj_filename[100]; char c_read_traj_filename[100]; char c_oflag[2]; char c_unbuffered[2]; char c_noretest[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_Q_flag[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_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[20]; /* 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_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[128]; char m_client_name[128]; char m_stop_flag; int m_client_number; int m_child_port; int m_child_async_port; int m_command; int m_testnum; int m_version; 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[128]; char m_client_name[128]; char m_client_number[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_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 CACHE_LINE_SIZE 32 #define 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 256 /* 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 10 /* 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_STRING1 "%16ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%9ld%9ld%8ld%10ld%9ld%10ld%9ld%10ld%10ld%9ld\n" #define CONTROL_STRING2 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s%8s%9s%7s%10s%10s%10s%9s%9s\n" #define CONTROL_STRING3 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING4 "%16s%8s%8s%8s%8s%10s\n" #else #define CONTROL_STRING1 "%16ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%9ld%9ld%8ld%10ld%9ld%10ld\n" #define CONTROL_STRING2 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s%8s%9s%7s%10s\n" #define CONTROL_STRING3 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s\n" #define CONTROL_STRING4 "%16s%8s%8s%8s%8s%10s\n" #endif #else #define CONTROL_STRING1 "%16ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%9ld%9ld\n" #define CONTROL_STRING2 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING3 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING4 "%16s%8s%8s%8s%8s%10s\n" #endif #endif #ifndef NO_PRINT_LLD #ifdef HAVE_PREAD #include #if defined(HAVE_PREAD) && defined(HAVE_PREADV) #define CONTROL_STRING1 "%16lld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%9ld%9ld%8ld%10ld%9ld%10ld%9ld%10ld%10ld%9ld\n" #define CONTROL_STRING2 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s%8s%9s%7s%10s%10s%10s%9s%9s\n" #define CONTROL_STRING3 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING4 "%16s%8s%8s%8s%8s%10s\n" #else #define CONTROL_STRING1 "%16lld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%9ld%9ld%8ld%10ld%9ld%10ld\n" #define CONTROL_STRING2 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s%8s%9s%7s%10s\n" #define CONTROL_STRING3 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING4 "%16s%8s%8s%8s%8s%10s\n" #endif #else #define CONTROL_STRING1 "%16lld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%8ld%9ld%9ld\n" #define CONTROL_STRING2 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING3 "%16s%8s%8s%8s%8s%10s%8s%8s%8s%8s%8s%9s%9s%8s%9s\n" #define CONTROL_STRING4 "%16s%8s%8s%8s%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 /******************************************************************/ /* */ /* FUNCTION DECLARATIONS */ /* */ /******************************************************************/ char *initfile(); void mmap_end(); void alloc_pbuf(); void auto_test(); /* perform automatic test series */ void show_help(); /* show development help */ static double time_so_far(); /* time since start of program */ #ifdef unix static double utime_so_far(); /* user time */ static double stime_so_far(); /* system time */ static double clk_tck(); /* Get clocks/tick */ static double cputime_so_far(); #else #define cputime_so_far() time_so_far() #endif static double time_so_far1(); /* time since start of program */ void get_resolution(); void get_rusage_resolution(); void signal_handler(); /* clean up if user interrupts us */ void begin(); /* The main worker in the app */ void fetchit(); /* Prime on chip cache */ void purgeit(); /* Purge on chip cache */ void throughput_test(); /* Multi process throughput */ void multi_throughput_test(); /* Multi process throughput */ void prepage(); /* Pre-fault user buffer */ void get_date(); int get_pattern(); /* Set pattern based on version */ #ifdef HAVE_ANSIC_C float do_compute(float); /* compute cycle simulation */ #else float do_compute(); /* compute cycle simulation */ #endif 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 dump_excel(); void dump_throughput(); int sp_start_child_send(); int sp_start_master_listen(); #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 void my_nap(); int thread_exit(); #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(); #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 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)(void *); void *(thread_write_test)(void *); void *(thread_read_test)(void*); #ifdef HAVE_PREAD void *(thread_pread_test)(void*); void *(thread_pwrite_test)(void*); #endif void *(thread_cleanup_test)(void*); void *(thread_cleanup_quick)(void*); void *(thread_ranread_test)(void *); void *(thread_mix_test)(void *); void *(thread_ranwrite_test)(void *); void *(thread_rread_test)(void *); void *(thread_reverse_read_test)(void *); void *(thread_stride_read_test)(void *); void *(thread_set_base)(void *); 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 do_speed_check(int); #else void do_speed_check(); #if !defined(linux) char *getenv(); char *inet_ntoa(); int system(); #endif void my_nap(); int thread_exit(); 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_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(); #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) #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) #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" }; */ char *test_output[] = {" ", " ", " ", " ", " ", " ", " ", " ", "", " ", " ", " \n" }; long long test_soutput[] = {2,2,2,1,1,1,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 r_count,s_count; char *barray[MAXSTREAMS]; char *haveshm; extern int optind; long long onetime, auto_mode, sfd, multi_buffer; 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; char aflag, Eflag, hflag, Rflag, rflag, sflag; char diag_v,sent_stop; char bif_flag; int rlocking; int share_file; char gflag,nflag; char yflag,qflag; #ifdef Windows char *build_name = "Windows"; #else char *build_name = NAME; #endif 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; 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; extern char *optarg; #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; 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 */ char tfile[] = "iozone"; char *buffer, *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=CACHE_SIZE; unsigned long cache_line_size=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"}; 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]; /* * 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) /* * 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_CLEANUP_TEST 12 /* * 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,s_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 = 18; /******************************************************************************/ /* 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[256]; struct child_ident { char child_name[100]; char workdir[256]; char execute_path[256]; 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 async_flag,stride_flag,mmapflag,mmapasflag,mmapssflag,mmapnsflag,mmap_mix; char verify = 1; int restf; char sverify = 1; char odsync = 0; char 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 r_traj_flag,w_traj_flag; 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 child_send(); int start_child_send(); int start_child_listen(); int start_child_listen_async(); void start_child_listen_loop(); void child_listen(); void child_listen_async(); void stop_child_send(); void stop_child_listen(); void cleanup_comm(); void master_send(); int start_master_send(); int start_master_listen(); void master_listen(); void stop_master_send(); void stop_master_listen(); long long start_child_proc(); int parse_client_line(); void wait_dist_join(); void tell_children_begin(); void start_master_listen_loop(); void wait_for_master_go(); void tell_master_ready(); void stop_master_listen_loop(); void tell_master_stats(); void become_client(); int pick_client(); long long start_child_proc(); int start_master_send(); void child_listen(); int start_child_listen(); void stop_master_send(); void stop_master_listen(); void stop_child_send(); void stop_child_listen(); int start_child_send(); void master_send(); void child_send(); void master_listen(); int start_master_listen(); void child_remove_files(); void terminate_child_async(); void distribute_stop(); void send_stop(); void cleanup_children(); /****************************************************************/ /* */ /* 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; 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,256); /* Try to find the actual VM page size, if possible */ #if defined (solaris) || defined (_HPUX_SOURCE) || defined (linux) || defined(IRIX) || defined (IRIX64) #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",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",depth); #endif async_flag++; break; case 'I': /* Use VXFS direct advisory or O_DIRECT from Linux or AIX , or O_DIRECTIO for TRU64 */ #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) direct_flag++; sprintf(splash[splash_line++],"\tO_DIRECT feature enabled\n"); break; #endif #if defined(TRU64) direct_flag++; sprintf(splash[splash_line++],"\tO_DIRECTIO feature enabled\n"); break; #endif #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",&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",kilobytes64); #else sprintf(splash[splash_line++],"\tFile size set to %lld KB\n",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 > (unsigned 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 { 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 #ifdef _HPUX_SOURCE num_processors= pthread_num_processors_np(); 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 = CACHE_SIZE; break; case 'L': /* Set processor cache line size */ cache_line_size = (long)(atoi(optarg)); if(cache_line_size == 0) cache_line_size = 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++; 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)(atoi(optarg))*1024); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ reclen = (long long)(1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ reclen = (long long)(1024 * 1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ reclen = (long long)(1024 * 1024 * 1024 *(long long)atoi(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; mint=maxt=num_child; trflag++; if(Uflag) { printf("Can not run throughput tests with unmount & remounts.\n"); exit(15); } 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 > 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)atoi(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)(1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ minimum_file_size = (long long)(1024 * 1024 * (long long)atoi(optarg)); } if(minimum_file_size < RECLEN_START/1024) minimum_file_size=(off64_t)(RECLEN_START/1024); #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tUsing minimum file size of %ld kilobytes.\n",minimum_file_size); #else sprintf(splash[splash_line++],"\tUsing minimum file size of %lld kilobytes.\n",minimum_file_size); #endif break; case 'g': /* Set maximum file size for auto mode */ gflag=1; maximum_file_size = (off64_t)atoi(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)(1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ maximum_file_size = (long long)(1024 * 1024 * (long long)atoi(optarg)); } if(maximum_file_size < RECLEN_START/1024) maximum_file_size=(off64_t)(RECLEN_START/1024); #ifdef NO_PRINT_LLD sprintf(splash[splash_line++],"\tUsing maximum file size of %ld kilobytes.\n",maximum_file_size); #else sprintf(splash[splash_line++],"\tUsing maximum file size of %lld kilobytes.\n",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)(atoi(optarg))*1024); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ min_rec_size = (long long)(1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ min_rec_size = (long long)(1024 * 1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ min_rec_size = (long long)(1024 * 1024 * 1024 *(long long)atoi(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/1024); #else sprintf(splash[splash_line++],"\tUsing Minimum Record Size %lld KB\n", min_rec_size/1024); #endif break; case 'q': /* Set max record size for auto mode */ qflag=1; max_rec_size = ((long long)(atoi(optarg))*1024); if(optarg[strlen(optarg)-1]=='k' || optarg[strlen(optarg)-1]=='K'){ max_rec_size = (long long)(1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='m' || optarg[strlen(optarg)-1]=='M'){ max_rec_size = (long long)(1024 * 1024 * atoi(optarg)); } if(optarg[strlen(optarg)-1]=='g' || optarg[strlen(optarg)-1]=='G'){ max_rec_size = (long long)(1024 * 1024 * 1024 *(long long)atoi(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 '+': /* printf("Plus option = >%s<\n",optarg);*/ switch (*((char *)optarg)) { case 'a': /* Example: Has argument */ subarg=argv[optind++]; /* if(subarg!=(char *)0) Error checking. */ /* printf("Plus option argument = >%s<\n",subarg);*/ break; case 'b': /* Example: Does not have an argument */ 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 '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 '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) 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++]; 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 '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; 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; default: printf("Unsupported Plus option -> %s <-\n",optarg); exit(0); break; } break; } } 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 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 #ifdef _HPUX_SOURCE if(ioz_processor_bind) { bind_cpu=begin_proc; 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 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) 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",kilobytes64); if(r_traj_flag || w_traj_flag) { if(!silent) printf("%8lld",(long long )0); } else { if(!silent) printf("%8lld",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 ", min_rec_size,min_file_size); #else printf("Error: record length %lld is greater than filesize %lld KB\n ", min_rec_size,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"; 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,kilobytes64); #else if(!silent) printf("\tEach %s writes a %lld Kbyte file in telemetry controlled records\n", port,kilobytes64); #endif } else { #ifdef NO_PRINT_LLD if(!silent) printf("\tEach %s writes a %ld Kbyte file in %ld Kbyte records\n", port,kilobytes64,reclen/1024); #else if(!silent) printf("\tEach %s writes a %lld Kbyte file in %lld Kbyte records\n", port,kilobytes64,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); } } } /**********************************************************/ /*************** 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; } /* 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((void *)xx); #else thread_rwrite_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_rwrite_test,xx); #else childids[xx] = mythread_create( thread_rwrite_test,(void *)(long)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; /**********************************************************/ /*************** 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 **********************************/ /**************************************************************/ 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((void *)xx); #else thread_read_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_read_test,xx); #else childids[xx] = mythread_create( thread_read_test,(void *)(long)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 jumpend; } jumpend: 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); } } } /**********************************************************/ /*************** 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; } 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((void *)xx); #else thread_rread_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_rread_test,xx); #else childids[xx] = mythread_create( thread_rread_test,(void *)(long)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); } } } /**********************************************************/ /*************** 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]); 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((void *)xx); #else thread_reverse_read_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_reverse_read_test,xx); #else childids[xx] = mythread_create( thread_reverse_read_test,(void *)(long)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); } } } 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]); 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((void *)xx); #else thread_stride_read_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_stride_read_test,xx); #else childids[xx] = mythread_create( thread_stride_read_test,(void *)(long)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); } } } 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]); 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((void *)xx); #else thread_ranread_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_ranread_test,xx); #else childids[xx] = mythread_create( thread_ranread_test,(void *)(long)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); } } } 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]); 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((void *)xx); #else thread_mix_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_mix_test,xx); #else childids[xx] = mythread_create( thread_mix_test,(void *)(long)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); } } } 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)) goto next6; toutputindex++; strcpy(&toutput[toutputindex][0],throughput_tests[8]); 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((void *)xx); #else thread_ranwrite_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_ranwrite_test,xx); #else childids[xx] = mythread_create( thread_ranwrite_test,(void *)(long)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); } } } 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]); 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((void *)xx); #else thread_pwrite_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_pwrite_test,xx); #else childids[xx] = mythread_create( thread_pwrite_test,(void *)(long)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); } } } 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]); 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((void *)xx); #else thread_pread_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ chid=xx; #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_pread_test,xx); #else childids[xx] = mythread_create( thread_pread_test,(void *)(long)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); } } } sync(); sleep(2); if(restf) sleep((int)rest_val); if(distributed && master_iozone) { stop_master_listen(master_listen_socket); cleanup_comm(); } #endif next8: 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((void *)xx); #else thread_cleanup_test((void *)((long)xx)); #endif } } } #ifndef NO_THREADS else { for(xx = 0; xx< num_child ; xx++){ /* Create the children */ #ifdef _64BIT_ARCH_ childids[xx] = mythread_create( thread_cleanup_test,xx); #else childids[xx] = mythread_create( thread_cleanup_test,(void *)(long)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(); } } /********************************************************/ /* 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; /* 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 } /************************************************************************/ /* 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; 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 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; 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; 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 == 2) { for(i=0;i<(length);i+=page_size) { dummy = *where; where+=(page_size/sizeof(long long)); } return(0); } 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",file_position); printf("Record # %ld Record size %ld kb \n",recnum,recsize/1024); printf("where %8.8llx loop %ld\n",where,i); #else printf("Error in file: Found ?%llx? Expecting ?%llx? addr %lx\n",*where, (long long)((pattern_buf<<32)|pattern_buf),((long)where)); printf("Error in file: Position %lld \n",file_position); printf("Record # %lld Record size %lld kb \n",recnum,recsize/1024); printf("where %8.8lx loop %lld\n",(long)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<(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>%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(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<(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 starttime1; double writetime[2]; double walltime[2], cputime[2]; double qtime_start,qtime_stop; 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; long long 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; 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) 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) 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. */ 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); } wval=ftruncate(fd,0); if(wval < 0) { printf("Sanity check failed. Do not deploy this filesystem in a production environment !\n"); exit(44); } close(fd); unlink(filename); /* Sanity check */ if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; pbuff = mbuffer + Index; if(verify) 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) fill_buffer(nbuff,reclen,(long long)pattern,sverify,i); if(purge) purgeit(nbuff,reclen); } if(purge) purgeit(pbuff,reclen); if(Q_flag) { 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"); signal_handler(); } #if defined(Windows) } #endif } } if(Q_flag) { qtime_stop=time_so_far(); if(j==0) #ifdef NO_PRINT_LLD fprintf(wqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,reclen); else fprintf(rwqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,reclen); #else fprintf(wqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,reclen); else fprintf(rwqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((qtime_stop-qtime_start-time_res))*1000000,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 fsync(fd); } 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 close(fd); } writetime[j] = ((time_so_far() - starttime1)-time_res) -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 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=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("%8ld",writerate[0]); if(!silent) printf("%8ld",writerate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%8lld",writerate[0]); if(!silent) printf("%8lld",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 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 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) 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"); signal_handler(); } } if(include_flush) { fflush(stream); fsync(fd); } if(include_close) { fclose(stream); } writetime[j] = ((time_so_far() - starttime1)-time_res) -compute_val; if(writetime[j] < (double).000001) { writetime[j]= time_res; if(rec_prob < reclen) rec_prob = reclen; res_prob=1; } if(!include_close) { fflush(stream); fclose(stream); } 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)(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 %ld %x\n", i, (unsigned long long)buffer); #else printf("\nError freading block %ld %x\n", i, (unsigned long long)buffer); #endif #else #ifdef NO_PRINT_LLD printf("\nError freading block %ld %lx\n", i, (long)buffer); #else printf("\nError freading block %lld %lx\n", 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); } 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("%8ld",readrate[0]); if(!silent) printf("%9ld",readrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%8lld",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; #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 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) 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) 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", i, (unsigned long long)nbuff); #else printf("\nError reading block %lld %llx\n", i, (unsigned long long)nbuff); #endif #else #ifdef NO_PRINT_LLD printf("\nError reading block %ld %x\n", i, (long)nbuff); #else printf("\nError reading block %lld %lx\n", 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(Q_flag) { qtime_stop=time_so_far(); if(j==0) #ifdef NO_PRINT_LLD fprintf(rqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,reclen); else fprintf(rrqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,reclen); #else fprintf(rqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,reclen); else fprintf(rrqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,(qtime_stop-qtime_start-time_res)*1000000,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); } 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 big_rand; long long rand1,rand2,rand3; #endif long long j; off64_t i,numrecs64; long long Index=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; #ifdef VXFS int test_foo=0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif maddr=free_addr=0; numrecs64 = (kilo64*1024)/reclen; flags = O_RDWR; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) 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(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(mmapflag) { maddr=(char *)initfile(fd,filebytes64,0,PROT_READ|PROT_WRITE); } nbuff=mainbuffer; if(fetchon) fetchit(nbuff,reclen); #ifdef bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #endif #endif compute_val=(double)0; starttime2 = time_so_far(); if ( j==0 ){ for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(purge) purgeit(nbuff,reclen); #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( !(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", offset64); #else printf("\nError reading block at %lld\n", 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); } } } else { if(verify) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); for(i=0; i (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } #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) fill_buffer(nbuff,reclen,(long long)pattern,sverify,offset64/reclen); } if(purge) purgeit(nbuff,reclen); if(verify & diag_v) 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", offset64); #else printf("\nError writing block at %lld\n", offset64); #endif if(wval==-1) perror("write"); signal_handler(); } } } 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 fsync(fd); } if(include_close) { if(mmapflag) { mmap_end(maddr,(unsigned long long)filebytes64); } close(fd); } randreadtime[j] = ((time_so_far() - starttime2)-time_res)- 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 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<2;j++) { randreadrate[j] = (unsigned long long) ((double) filebytes64 / randreadtime[j]); if(MS_flag) { randreadrate[j]=1000000.0*(1.0/randreadrate[j]); continue; } 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("%8ld",randreadrate[0]); if(!silent) printf("%8ld",randreadrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%8lld",randreadrate[0]); if(!silent) printf("%8lld",randreadrate[1]); if(!silent) fflush(stdout); #endif } /************************************************************************/ /* 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; #ifdef VXFS 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) 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", i); #else printf("\nError reading block %lld\n", 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); } 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("%8ld",revreadrate[0]); #else if(!silent) printf("%8lld",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 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; #ifdef VXFS 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; #if ! defined(DONT_HAVE_O_DIRECT) #if defined(linux) || defined(__AIX__) || defined(IRIX) || defined(IRIX64) 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) unlink(dummyfile[0]); if(Uflag) /* Unmount and re-mount the mountpoint */ { purge_buffer_cache(); } if((fd = I_OPEN(dummyfile[0], (int)flags,0640))<0) { printf("\nCan not open temporary file %s for write.\n",dummyfile[0]); 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(mmapflag) { maddr=(char *)initfile(fd,filebytes64,1,PROT_READ|PROT_WRITE); } #ifdef ASYNC_IO if(async_flag) async_init(&gc,fd,direct_flag); #endif fsync(fd); 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", 0, fd); #else printf("\nError writing block %lld, fd= %d\n", 0, fd); #endif if(wval==-1) perror("write"); signal_handler(); } */ if(verify) 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) fill_buffer(nbuff,reclen,(long long)pattern,sverify,(long long)0); } if(verify & diag_v) 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", i, fd); #else printf("\nError writing block %lld, fd= %d\n", i, fd); #endif if(wval==-1) perror("write"); signal_handler(); } } } 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 fsync(fd); } if(include_close) { if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); close(fd); } 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; } 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 fsync(fd); if(mmapflag) mmap_end(maddr,(unsigned long long)filebytes64); close(fd); } if(OPS_flag || MS_flag){ filebytes64=filebytes64/reclen; } writeinrate = (unsigned long long) ((double) filebytes64 / writeintime); if(MS_flag) { writeinrate=1000000.0*(1.0/writeinrate); } 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("%8ld",writeinrate); #else if(!silent) printf("%8lld",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; #ifdef VXFS 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) 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(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", i, fd,filename,uu); printf("\nSeeked to %ld Reclen = %ld\n", savepos64,reclen); #else printf("\nError reading block %lld, fd= %d Filename %s Read returned %lld\n", i, fd,filename,uu); printf("\nSeeked to %lld Reclen = %lld\n", savepos64,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); } 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; } strideinrate = (unsigned long long) ((double) filebytes64 / strideintime); if(MS_flag) { strideinrate=1000000.0*(1.0/strideinrate); } 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("%8ld",strideinrate); #else if(!silent) printf("%8lld",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 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; off64_t numrecs64,traj_offset; off64_t lock_offset=0; long long traj_size; #ifdef VXFS 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) if(direct_flag) flags_here |=O_DIRECT; #endif #if defined(TRU64) if(direct_flag) flags_here |=O_DIRECTIO; #endif #endif unlink(filename); if(noretest) ltest=1; else ltest=2; for( j=0; j (MAXBUFFERSIZE-reclen)) Index=0; nbuff = mbuffer + Index; } if(verify && diag_v) 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", i, fd); #else printf("\nError pwriting block %lld, fd= %d\n", i, fd); #endif perror("pwrite"); signal_handler(); } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } } if(include_flush) { fsync(fd); } if(include_close) { close(fd); } pwritetime[j] = ((time_so_far() - starttime1)-time_res) -compute_val; if(pwritetime[j] < (double).000001) { pwritetime[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); } 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",pwriterate[0]); if(!silent) printf("%9ld",pwriterate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%8lld",pwriterate[0]); if(!silent) printf("%9lld",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; #ifdef VXFS 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) 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 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", i,(unsigned long)nbuff); #else printf("\nError reading block %lld %lx\n", 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); 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",preadrate[0]); if(!silent) printf("%9ld",preadrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%8lld",preadrate[0]); if(!silent) printf("%9lld",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 { 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; #ifdef VXFS int test_foo = 0; #endif long long flags_here; char *nbuff; 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) 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",pwritevrate[0]); if(!silent) printf("%10ld",pwritevrate[1]); if(!silent) fflush(stdout); #else if(!silent) printf("%9lld",pwritevrate[0]); if(!silent) printf("%10lld",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 { off64_t offset; long long found,i,j; long long numvecs; #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; long long big_rand; #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",preadvrate[0]); if(!silent) printf("%9ld",preadvrate[1]); if(!silent) printf("\n"); if(!silent) fflush(stdout); #else if(!silent) printf("%10lld",preadvrate[0]); if(!silent) printf("%9lld",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",042,rec_size/1024,042); #else if(!silent) printf(" %c%lld%c",042,rec_size/1024,042); #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 ",042,current_file_size,042); #else if(!silent) printf("%c%lld%c ",042,current_file_size,042); #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 ",042,current_file_size,042); #else if(!silent) printf("%c%lld%c ",042,current_file_size,042); #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 ",report_array[who][i]); #else if(!silent) printf(" %lld ",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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,rec_size/1024,042); #else if(!silent) printf(" %c%lld%c",042,rec_size/1024,042); #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 ",042,current_file_size,042); #else if(!silent) printf("%c%lld%c ",042,current_file_size,042); #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 ",042,current_file_size,042); #else if(!silent) printf("%c%lld%c ",042,current_file_size,042); #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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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",042,042); 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; int shmid; 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 = %d, Error %d\n",shmid,size,(size_t)size1,errno); #else printf("shmid = %d, size = %lld, size1 = %d, Error %d\n",shmid,size,(size_t)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); #ifdef bsd4_2 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 %d\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 { long long i; for(i=mint;i<=maxt;i++){ num_child =i; current_client_number=0; /* Need to start with 1 */ throughput_test(); current_x=0; current_y++; } if(Rflag) dump_throughput(); } /************************************************************************/ /* 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]; strcpy(command,"umount "); strcat(command, mountname); system(command); strcpy(command,"mount "); strcat(command, mountname); system(command); } /************************************************************************/ /* Thread write test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_write_test(void *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; 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; #ifdef VXFS 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; 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 #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",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; #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],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); } else { #endif if((fd = I_CREAT(dummyfile[xx], 0640))<0) { perror(dummyfile[xx]); exit(123); } #if defined(Windows) } #endif #if defined(Windows) if(unbuffered) CloseHandle(hand); else { #endif close(fd); #if defined(Windows) } #endif if(oflag) flags=O_RDWR|O_SYNC; else flags=O_RDWR; #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) 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,0))<0) { printf("\nCan not open temp file: %s\n", filename); 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 #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) 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) { 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(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) { 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) { 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; 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) { 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) 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); #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; 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", i, fd); #else printf("\nError writing block %lld, fd= %d\n", i, fd); #endif if(wval==-1) perror("write"); if (!no_unlink) unlink(dummyfile[xx]); child_stat->flag = CHILD_STATE_HOLD; exit(127); } } } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_wqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_wqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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(); 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_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) { printf(" child/slot: %lld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n", xx, 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",xx); #else printf("\nChild finished %lld\n",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(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(void *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; 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; #ifdef VXFS 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; 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 #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",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; #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],xx2); #endif /*****************/ /* Children only */ /*******************************************************************/ /* Initial write throughput performance test. **********************/ /*******************************************************************/ if((fd = I_CREAT(dummyfile[xx], 0640))<0) { perror(dummyfile[xx]); exit(123); } close(fd); if(oflag) flags=O_RDWR|O_SYNC; else flags=O_RDWR; #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) 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) { printf("\nCan not open temp file: %s\n", filename); 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 #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) 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) { 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(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) { 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) { 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 = (time_so_far() - 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; } if(purge) purgeit(nbuff,reclen); if(Q_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) 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", i, fd); #else printf("\nError pwriting block %lld, fd= %d\n", i, fd); #endif if(wval==-1) perror("pwrite"); if (!no_unlink) unlink(dummyfile[xx]); child_stat->flag = CHILD_STATE_HOLD; exit(127); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_wqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_wqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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(); 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_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) { printf(" child/slot: %lld, wall-cpu: %8.3f %8.3fC" " -> %6.2f%%\n", xx, 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",xx); #else printf("\nChild finished %lld\n",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(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(void *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; 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]; #ifdef VXFS int test_foo = 0; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif if(compute_flag) delay=compute_time; wmaddr=nbuff=maddr=free_addr=0; thread_rwqfd=w_traj_fd=thread_Lwqfd=(FILE *)0; 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 #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; 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",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; #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],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) 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) { #ifdef NO_PRINT_LLD printf("\nChild %ld\n",xx); #else printf("\nChild %lld\n",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 #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); 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) { 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) printf("Child %d waiting for go from master\n",(int)xx); wait_for_master_go(chid); if(cdebug) printf("Child %d received go from master\n",(int)xx); } 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) 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(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rwqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_rwqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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]; 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_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) printf("Child %d: throughput %f actual %f \n",(int)chid, child_stat->throughput, child_stat->actual); 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",xx); #else printf("\nChild Stopping %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Rewrite test finished: ",now_string); fclose(thread_Lwqfd); } 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(void *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 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; #ifdef VXFS 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; 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; #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) 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) { 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(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",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 } /*****************/ /* Children only */ /*****************/ if(Q_flag) { sprintf(tmpname,"Child_%d_rol.dat",(int)xx); thread_rqfd=fopen(tmpname,"a"); if(thread_rqfd==0) { 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) { 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) 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) 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(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_rqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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]; 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) printf("Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); 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",xx); #else printf("\nChild finished %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Read test finished: ",now_string); fclose(thread_Lwqfd); } 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(void *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 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; #ifdef VXFS 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; 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; #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) 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) { 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(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",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 } /*****************/ /* Children only */ /*****************/ if(Q_flag) { sprintf(tmpname,"Child_%d_prol.dat",(int)xx); thread_rqfd=fopen(tmpname,"a"); if(thread_rqfd==0) { 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) { 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) 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) 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(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_rqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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]; 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) printf("Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); 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",xx); #else printf("\nChild finished %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Pread test finished: ", now_string); fclose(thread_Lwqfd); } 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(void *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 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]; #ifdef VXFS 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; 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 #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",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; #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) 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) { 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(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) { 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) { 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) 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) 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(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_rrqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_rrqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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(); 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(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(void *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 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; #ifdef VXFS 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; 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 #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",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; #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) 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) { 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(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) { 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) { 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((I_LSEEK( fd, -t_offset, SEEK_END ))<0) { perror("lseek"); exit(142); }; } 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) 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) 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(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_revqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_revqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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->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",xx); #else printf("\nChild finished %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Reverse read finished: ", now_string); fclose(thread_Lwqfd); } 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(void *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 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; #ifdef VXFS 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; 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 #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",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; #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) 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) { 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(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) { 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) { 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) 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) 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) { 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) { perror("lseek"); exit(154); }; } } stride_read +=reclen/1024; if(*stop_flag) { stride_read -=reclen/1024; } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_strqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_strqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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->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",xx); #else printf("\nChild finished %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Stride test finished: ", now_string); fclose(thread_Lwqfd); } 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(void *x) #else void * thread_mix_test(x) #endif { int selector; int num_readers; long xx; #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(cdebug || mdebug) printf("Mix read %d\n",selector); if(seq_mix) thread_read_test(x); else thread_ranread_test(x); } else { if(cdebug || mdebug) printf("Mix write %d\n",selector); if(seq_mix) thread_write_test(x); else thread_ranwrite_test(x); } return(0); } /************************************************************************/ /* Thread random read test */ /************************************************************************/ #ifdef HAVE_ANSIC_C void * thread_ranread_test(void *x) #else void * thread_ranread_test(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 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; #ifdef VXFS int test_foo = 0; #endif long long save_pos; #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; long long big_rand; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif if(compute_flag) delay=compute_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 #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; #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) 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) { 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(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",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 } /*****************/ /* 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) { 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) { 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 bsd4_2 srand(0); #else #ifdef Windows srand(0); #else srand48(0); #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) 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) 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(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_randrfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_randrfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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]; 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) printf("Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); 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",xx); #else printf("\nChild finished %lld\n",xx); #endif if(L_flag) { get_date(now_string); fprintf(thread_Lwqfd,"%-25s %s","Random read finished: ",now_string); fclose(thread_Lwqfd); } 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(void *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; 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; #ifdef VXFS int test_foo = 0; #endif #if defined (bsd4_2) || defined(Windows) long long rand1,rand2,rand3; long long big_rand; #endif #ifdef ASYNC_IO struct cache *gc=0; #else long long *gc=0; #endif if(compute_flag) delay=compute_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 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",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; #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx2],xx2); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx2],xx2); #endif /*****************/ /* Children only */ /*******************************************************************/ /* Random write throughput performance test. **********************/ /*******************************************************************/ #ifdef foobar if((fd = I_CREAT(dummyfile[xx], 0640))<0) { perror(dummyfile[xx]); exit(123); } close(fd); #endif if(oflag) flags=O_RDWR|O_SYNC; else flags=O_RDWR; #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) 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) { printf("\nCan not open temp file: %s\n", filename); 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 #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) { 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) { 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) 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; 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) { 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) 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); 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 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"); if (!no_unlink) unlink(dummyfile[xx]); child_stat->flag = CHILD_STATE_HOLD; exit(127); } } } if(rlocking) { mylockr((int) fd, (int) 0, (int)0, lock_offset, reclen); } if(Q_flag) { thread_qtime_stop=time_so_far(); #ifdef NO_PRINT_LLD fprintf(thread_randwqfd,"%10.1ld %10.0f %10.1ld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,reclen); #else fprintf(thread_randwqfd,"%10.1lld %10.0f %10.1lld\n",(traj_offset)/1024,((thread_qtime_stop-thread_qtime_start-time_res))*1000000,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(); 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; } child_stat->flag = CHILD_STATE_HOLD; /* Tell parent I'm done */ if(cdebug) printf("Child %d: throughput %f actual %f \n",(int)chid,child_stat->throughput, child_stat->actual); 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",xx); #else printf("\nChild finished %lld\n",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(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(void *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); #ifdef NO_PRINT_LLD sprintf(dummyfile[xx],"%s.DUMMY.%ld",filearray[xx],xx); #else sprintf(dummyfile[xx],"%s.DUMMY.%lld",filearray[xx],xx); #endif if(!no_unlink) 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 *),void *x) #else long long mythread_create( func,x) void *(*func)(void *); void *x; #endif { pthread_t ts; pthread_attr_t attr; int xx; int *yy; #ifdef _64BIT_ARCH_ long long meme; meme = (long long)x; #else long meme; meme = (long)x; #endif yy=(int *)x; #ifdef OSFV3 xx=(int )pthread_create(&ts, pthread_attr_default, func, (void *)yy); #else pthread_attr_init(&attr); xx=(int )pthread_create((pthread_t *)&ts, (pthread_attr_t *) &attr, func, (void *)yy); #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 %lx\n",ts); printf("meme %ld\n",meme); } return((long long)meme); } #else #ifdef HAVE_ANSIC_C long long mythread_create( void *(*func)(void *),void *x) #else long long mythread_create( func,x) void *(*func)(void *); void *x; #endif { printf("This version does not support threads\n"); } #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); return(0); } #else #ifdef HAVE_ANSIC_C int thread_exit(void) #else int thread_exit() #endif { printf("This version does not support threads\n"); } #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"); } #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"); } #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", reclen/1024); #else if(!silent) printf("\"Record size = %lld Kbytes \"\n", 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", reclen/1024); #else sprintf(print_str, "Record size = %lld Kbytes", 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",reclen/1024); #else if(!silent) printf("\"Record size = %lld Kbytes \"\n",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",reclen/1024); #else sprintf(print_str,"Record size = %lld Kbytes",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) 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 (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); } return(0.0); } /************************************************************************/ /* 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) read(fd,nbuff,page_size); else read(fd,nbuff,1); /* Skip into the file */ I_LSEEK(fd,page_size,SEEK_SET); /* Read a little of the file */ if(direct_flag) read(fd,nbuff,page_size); else 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; long long tmp2 = 0; 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",&traj_offset,&tmp2,&tmp); #else ret=sscanf(sbuf,"%lld %lld %d\n",&traj_offset,&tmp2,&tmp); #endif /*printf("\nReading %s trajectory with %d items\n",which?"write":"read",tokens);*/ *traj_size=tmp2; *delay= ((float)tmp/1000); } if(tokens == 2) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld\n",&traj_offset,traj_size); #else ret=sscanf(sbuf,"%lld %lld\n",&traj_offset,traj_size); #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 %lld Size %ld Compute delay %f\n",traj_offset, *traj_size,*delay); #else if(!silent) printf("\nOffset %lld Size %lld Compute delay %f\n",traj_offset, *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",&traj_offset,&traj_size,&dummy); #else ret=sscanf(sbuf,"%lld %lld %d\n",&traj_offset,&traj_size,&dummy); #endif } if(tokens==2) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld\n",&traj_offset,&traj_size); #else ret=sscanf(sbuf,"%lld %lld\n",&traj_offset,&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 printf("File size of read %lld Item count %lld\n",r_traj_fsize,r_traj_ops); #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",&traj_offset,&traj_size,&dummy); #else ret=sscanf(sbuf,"%lld %lld %d",&traj_offset,&traj_size,&dummy); #endif } if(tokens==2) { #ifdef NO_PRINT_LLD ret=sscanf(sbuf,"%ld %ld\n",&traj_offset,&traj_size); #else ret=sscanf(sbuf,"%lld %lld\n",&traj_offset,&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 printf("File size of write %lld Item count %lld\n",w_traj_fsize,w_traj_ops); #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. int start_child_send(char *controlling_host_name) Call to start a send channel to 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; s = socket(AF_INET, SOCK_DGRAM, 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\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); } return(s); } /* * Master listens for messages and blocks until * something arrives. */ #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 rcvd; int s; int rc=0; tsize = size_of_message; s = sock; rcvd = 0; while(rcvd < tsize) { if(mdebug ==1) { printf("Master: In recieve \n"); fflush(stdout); } rc=recv(s,master_rcv_buf,size_of_message,0); if(rc < 0) { perror("Read failed\n"); exit(21); } if(mdebug >=1) { printf("Master got %d bytes\n",rc); fflush(stdout); } rcvd+=rc; } if(mdebug >=1) { printf("Master returning from got %d bytes\n",rc); fflush(stdout); } } /* * Child sends message to master. */ #ifdef HAVE_ANSIC_C void child_send(int child_socket_val, char *controlling_host_name, struct master_command *send_buffer, int send_size) #else void child_send(child_socket_val, controlling_host_name, send_buffer, send_size) int child_socket_val; char *controlling_host_name; struct master_command *send_buffer; int send_size; #endif { int rc; struct master_neutral_command outbuf; bzero(&outbuf, sizeof(struct master_neutral_command)); if(cdebug>=1) { printf("Child %d sending message to %s \n",(int)chid, controlling_host_name); fflush(stdout); } /* * 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_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_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",send_buffer->m_child_flag); #else sprintf(outbuf.m_child_flag,"%lld",send_buffer->m_child_flag); #endif if(cdebug>=1) { printf("Child %d sending message to %s\n",(int)chid, controlling_host_name); fflush(stdout); } rc = send(child_socket_val, (char *)&outbuf, sizeof(struct master_neutral_command), 0); if (rc < 0) { perror("write failed\n"); exit(26); } } /* * 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 = %d\n",sizeof(struct master_neutral_command)); printf("Client_neutral_command size = %d\n",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_client_name,send_buffer->c_client_name); strcpy(outbuf.c_working_dir,send_buffer->c_working_dir); 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_unbuffered,"%d",send_buffer->c_unbuffered); sprintf(outbuf.c_noretest,"%d",send_buffer->c_noretest); 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_Q_flag,"%d",send_buffer->c_Q_flag); 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_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_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); #ifdef NO_PRINT_LLD sprintf(outbuf.c_stride,"%ld",send_buffer->c_stride); sprintf(outbuf.c_rest_val,"%ld",send_buffer->c_rest_val); sprintf(outbuf.c_delay,"%ld",send_buffer->c_delay); sprintf(outbuf.c_purge,"%ld",send_buffer->c_purge); sprintf(outbuf.c_fetchon,"%ld",send_buffer->c_fetchon); sprintf(outbuf.c_numrecs64,"%ld",send_buffer->c_numrecs64); sprintf(outbuf.c_reclen,"%ld",send_buffer->c_reclen); sprintf(outbuf.c_child_flag,"%ld",send_buffer->c_child_flag); sprintf(outbuf.c_delay_start,"%ld",send_buffer->c_delay_start); sprintf(outbuf.c_depth,"%ld",send_buffer->c_depth); #else sprintf(outbuf.c_delay,"%lld",send_buffer->c_delay); sprintf(outbuf.c_stride,"%lld",send_buffer->c_stride); sprintf(outbuf.c_rest_val,"%lld",send_buffer->c_rest_val); sprintf(outbuf.c_purge,"%lld",send_buffer->c_purge); sprintf(outbuf.c_fetchon,"%lld",send_buffer->c_fetchon); sprintf(outbuf.c_numrecs64,"%lld",send_buffer->c_numrecs64); sprintf(outbuf.c_reclen,"%lld",send_buffer->c_reclen); sprintf(outbuf.c_child_flag,"%lld",send_buffer->c_child_flag); sprintf(outbuf.c_delay_start,"%lld",send_buffer->c_delay_start); sprintf(outbuf.c_depth,"%lld",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); } } /* * Client setting up the channel for sending messages to the master. */ #ifdef HAVE_ANSIC_C int start_child_send(char *controlling_host_name) #else int start_child_send(controlling_host_name) char *controlling_host_name; #endif { int rc,child_socket_val; int ecount = 0; struct sockaddr_in addr,raddr; struct hostent *he; int tmp_port; struct in_addr *ip; he = gethostbyname(controlling_host_name); if (he == NULL) { if(cdebug) { printf("Child %d: Bad server host %s\n",(int)chid, controlling_host_name); fflush(stdout); } exit(22); } if(cdebug ==1) { printf("Child %d: start child send to hostname: %s\n",(int)chid, he->h_name); fflush(stdout); } ip = (struct in_addr *)he->h_addr_list[0]; #ifndef UWIN if(cdebug ==1) { printf("Child %d: server host: %s\n",(int)chid, (char *)inet_ntoa(*ip)); fflush(stdout); } #endif raddr.sin_family = AF_INET; raddr.sin_port = htons(HOST_LIST_PORT); raddr.sin_addr.s_addr = ip->s_addr; child_socket_val = socket(AF_INET, SOCK_DGRAM, 0); if (child_socket_val < 0) { perror("Child: socket failed:"); exit(23); } bzero(&addr, sizeof(struct sockaddr_in)); tmp_port=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(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) { printf("Child %d: Bound to host port %d\n",(int)chid, tmp_port); fflush(stdout); } if (rc < 0) { perror("Child: bind failed\n"); exit(24); } again: rc = connect(child_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++<300) { sleep(1); goto again; } perror("Child: connect failed\n"); exit(25); } if(cdebug ==1) { printf("Child %d Connected\n",(int)chid); fflush(stdout); } return (child_socket_val); } /* * 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 stop_child_send(int child_socket_val) #else void 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 { close(master_socket_val); } /* * 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; 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\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) { printf("Child %d: Listen: Bound at port %d\n",(int)chid, tmp_port); fflush(stdout); } if(rc < 0) { perror("bind failed\n"); 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 { int me,ns; struct sockaddr_in *addr; if(flag) { addr=&child_async_sock; if(cdebug) { printf("Child %d attach async\n",(int)chid); fflush(stdout); } } else { addr=&child_sync_sock; if(cdebug) { printf("Child %d attach sync\n",(int)chid); fflush(stdout); } } me=sizeof(struct sockaddr_in); if(cdebug) { printf("Child %d enters listen\n",(int)chid); fflush(stdout); } listen(s,10); if(cdebug) { printf("Child %d enters accept\n",(int)chid); fflush(stdout); } ns=accept(s,(void *)addr,&me); if(cdebug) { printf("Child %d attached for receive. Sock %d %d\n",(int)chid, ns,errno); fflush(stdout); } 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) { printf("Child %d In recieve \n",(int)chid); fflush(stdout); } /*rc=recv(s,child_rcv_buf,size_of_message,0);*/ rc=read(s,cnc,size_of_message); if(rc < 0) { perror("Read failed\n"); exit(21); } if(cdebug >= 1) { printf("Child %d: Got %d bytes\n",(int)chid, rc); fflush(stdout); } rcvd+=rc; cnc+=rc; } if(cdebug >= 1) { printf("Child %d: return from listen\n",(int)chid); fflush(stdout); } } /* * 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; 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\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) { printf("Child %d: Async Listen: Bound at port %d\n",(int)chid,tmp_port); fflush(stdout); } if(rc < 0) { perror("bind failed\n"); 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) { printf("Child %d In async recieve \n",(int)chid); fflush(stdout); } /*rc=recv(s,child_async_rcv_buf,size_of_message,0);*/ rc=read(s,cnc,size_of_message); if(rc < 0) { perror("Read failed\n"); exit(21); } if(cdebug >= 1) { printf("Child %d: Got %d bytes (async) \n",(int)chid,rc); fflush(stdout); } rcvd+=rc; cnc+=rc; } if(cdebug >= 1) { printf("Child %d: return from async listen\n",(int)chid); fflush(stdout); } } /* * 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; 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); } again: rc = connect(master_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++ < 300) { 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; port=child_port; /* Silly, fragile socket code... Sleep 1 sec here * or some accept()/connect() pairs will hang * and fail. gosh, ain't a standard API fun !! */ sleep(1); 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) { sleep(1); goto again; } perror("Master: async connect failed\n"); exit(25); } 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; 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); strcat(command," '"); 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 !!\n", child_idents[x-1].child_name); } 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_client_name ,child_idents[x-1].child_name); strcpy(cc.c_working_dir ,child_idents[x-1].workdir); 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_unbuffered = unbuffered; cc.c_noretest = noretest; 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_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_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_Q_flag = Q_flag; 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_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",&mc.m_child_flag); #else sscanf(mnc->m_child_flag,"%lld",&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[256]; 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,256); 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) { printf("My name = %s, Controller's name = %s\n",client_name, controlling_host_name); } /* 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. Start client send channel */ s_sock = start_child_send(controlling_host_name); /* 3. 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) { printf("Child %s sends JOIN to master %s My port %d\n", client_name,controlling_host_name,child_port); fflush(stdout); } child_send(s_sock, 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) { printf("Child %s waiting for who am I\n",client_name); fflush(stdout); } 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); if(cc.c_command == R_TERMINATE || cc.c_command==R_DEATH) { if(cdebug) { printf("Child %d received terminate on sync channel !!\n",(int)chid); fflush(stdout); } exit(1); } if(cdebug) { printf("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(stdout); } /* * 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",&cc.c_numrecs64); sscanf(cnc->c_reclen,"%ld",&cc.c_reclen); sscanf(cnc->c_fetchon,"%ld",&cc.c_fetchon); sscanf(cnc->c_purge,"%ld",&cc.c_purge); sscanf(cnc->c_delay,"%ld",&cc.c_delay); sscanf(cnc->c_stride,"%ld",&cc.c_stride); sscanf(cnc->c_rest_val,"%ld",&cc.c_rest_val); sscanf(cnc->c_delay_start,"%ld",&cc.c_delay_start); sscanf(cnc->c_depth,"%ld",&cc.c_depth); #else sscanf(cnc->c_numrecs64,"%lld",&cc.c_numrecs64); sscanf(cnc->c_reclen,"%lld",&cc.c_reclen); sscanf(cnc->c_fetchon,"%lld",&cc.c_fetchon); sscanf(cnc->c_purge,"%lld",&cc.c_purge); sscanf(cnc->c_delay,"%lld",&cc.c_delay); sscanf(cnc->c_stride,"%lld",&cc.c_stride); sscanf(cnc->c_rest_val,"%lld",&cc.c_rest_val); sscanf(cnc->c_delay_start,"%lld",&cc.c_delay_start); sscanf(cnc->c_depth,"%lld",&cc.c_depth); #endif 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_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_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_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_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_oflag,"%d",&cc.c_oflag); sscanf(cnc->c_unbuffered,"%d",&cc.c_unbuffered); sscanf(cnc->c_Q_flag,"%d",&cc.c_Q_flag); 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_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; reclen = cc.c_reclen; testnum = cc.c_testnum; chid = cc.c_client_number; workdir=cc.c_working_dir; oflag = cc.c_oflag; unbuffered = cc.c_unbuffered; noretest = cc.c_noretest; 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; 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; 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; Q_flag = cc.c_Q_flag; 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; 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(cdebug) { printf("Child %d change directory to %s\n",(int)chid,workdir); fflush(stdout); } if(purge) alloc_pbuf(); /* 6. Change to the working directory */ chdir(workdir); 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(); /* 7. Run the test */ switch(testnum) { case THREAD_WRITE_TEST : if(cdebug>=1) { printf("Child %d running thread_write_test\n",(int)chid); fflush(stdout); } thread_write_test((long)0); break; #ifdef HAVE_PREAD case THREAD_PWRITE_TEST : if(cdebug>=1) { printf("Child %d running thread_pwrite_test\n",(int)chid); fflush(stdout); } thread_pwrite_test((long)0); break; #endif case THREAD_REWRITE_TEST : if(cdebug>=1) { printf("Child %d running thread_rewrite_test\n",(int)chid); fflush(stdout); } thread_rwrite_test((long)0); break; case THREAD_READ_TEST : if(cdebug>=1) { printf("Child %d running thread_read_test\n",(int)chid); fflush(stdout); } thread_read_test((long)0); break; #ifdef HAVE_PREAD case THREAD_PREAD_TEST : if(cdebug>=1) { printf("Child %d running thread_read_test\n",(int)chid); fflush(stdout); } thread_pread_test((long)0); break; #endif case THREAD_REREAD_TEST : if(cdebug>=1) { printf("Child %d running thread_reread_test\n",(int)chid); fflush(stdout); } thread_rread_test((long)0); break; case THREAD_STRIDE_TEST : if(cdebug>=1) { printf("Child %d running thread_stride_read_test\n",(int)chid); fflush(stdout); } thread_stride_read_test((long)0); break; case THREAD_RANDOM_READ_TEST : if(cdebug>=1) { printf("Child %d running random read test\n",(int)chid); fflush(stdout); } thread_ranread_test((long)0); break; case THREAD_RANDOM_WRITE_TEST : if(cdebug>=1) { printf("Child %d running random write test\n",(int)chid); fflush(stdout); } thread_ranwrite_test((long)0); break; case THREAD_REVERSE_READ_TEST : if(cdebug>=1) { printf("Child %d running reverse read test\n",(int)chid); fflush(stdout); } thread_reverse_read_test((long)0); break; case THREAD_RANDOM_MIX_TEST : if(cdebug>=1) { printf("Child %d running mixed workload test\n",(int)chid); fflush(stdout); } thread_mix_test((long)0); break; case THREAD_CLEANUP_TEST : if(cdebug>=1) { printf("Child %d running cleanup\n",(int)chid); fflush(stdout); } thread_cleanup_test((long)0); break; }; if(cdebug>=1) { printf("Child %d finished running test.\n",(int)chid); fflush(stdout); } /* 8. Release the listen and send sockets to the master */ stop_child_listen(l_sock); stop_child_send(s_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(testnum , chid, throughput, actual, cpu_time, wall_time, stop_flag, child_flag) int testnum; long long chid; double throughput, actual, wall_time; float cpu_time; char stop_flag; long long child_flag; /* void tell_master_stats(int testnum , long long chid, double tthroughput, double actual, float cpu_time, float 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_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_version = proto_version; if(cdebug>=1) { printf("Child %d: Tell master stats and terminate\n",(int)chid); fflush(stdout); } child_send(s_sock, 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) { printf("Child %d: Tell master to go\n",(int)chid); fflush(stdout); } mc.m_command = R_FLAG_DATA; mc.m_version = proto_version; mc.m_child_flag = CHILD_STATE_READY; mc.m_client_number = (int)chid; child_send(s_sock, 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) { printf("Child %d received terminate on sync channel at barrier !!\n",(int)chid); fflush(stdout); } exit(1); } if(cdebug>=1) printf("Child %d return from wait_for_master_go\n",(int)chid); } /* * 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; 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_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); } #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: 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(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(mdebug) printf("Master loop: R_STOP_FLAG: Client %d STOP_FLAG \n", (int)mc.m_client_number); *stop_flag=1; distribute_stop(); break; } } sleep(2); /* 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. */ 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) printf("Child %d starting client listen loop\n",(int)chid); 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) printf("child loop: R_STOP_FLAG for client %d\n",i); 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) { printf("Child loop: R_TERMINATE: Client %d \n", (int)cc.c_client_number); fflush(stdout); } sleep(2); /* Aync listener goes away */ stop_child_listen(l_async_sock); exit(0); case R_DEATH: if(cdebug) { printf("Child loop: R_DEATH: Client %d \n", (int)cc.c_client_number); fflush(stdout); } 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_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[200]; 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) { ret1=fgets(buffer,200,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\n", child_idents[line_num].child_name, child_idents[line_num].workdir, child_idents[line_num].execute_path); if((num > 0) && (num !=3)) { 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); } 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); sprintf(dummyfile[i],"%s.DUMMY.%d",filearray[i],i); if(cdebug) { printf("Child %d remove: %s \n",(int)chid, 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); write(msfd,mybuf,1024); if(cdebug) printf("Sending result\n"); 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; 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); } again: rc = connect(master_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++ < 300) { 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,me; int rc; int xx; int tmp_port; struct sockaddr_in *addr; int sockerr; int recv_buf_size=65536; 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\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) { printf("Child: Listen: Bound at port %d\n", tmp_port); fflush(stdout); } if(rc < 0) { perror("bind failed\n"); exit(20); } addr=&sp_child_async_sock; listen(s,10); if(cdebug) { printf("Child enters accept\n"); fflush(stdout); } ns=accept(s,(void *)addr,&me); if(cdebug) { printf("Child attached for receive. Sock %d %d\n", ns,errno); fflush(stdout); } 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) { printf("Child: start child send: %s\n", he->h_name); printf("To: %s at port %d\n",sp_master_host_name, sp_master_listen_port); fflush(stdout); } 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) { printf("Child: Bound port %d\n",tmp_port); fflush(stdout); } if (rc < 0) { perror("Child: bind failed for sync channel to child.\n"); exit(24); } again: rc = connect(sp_child_socket_val, (struct sockaddr *)&raddr, sizeof(struct sockaddr_in)); if (rc < 0) { if(ecount++<300) { sleep(1); goto again; } perror("child: connect failed\n"); printf("Error %d\n",errno); exit(25); } if(cdebug ==1) { printf("child Connected\n"); fflush(stdout); } 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, 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 == 15 ); 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 data style lines set dgrid3d 80,80,3 set terminal png small picsize 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 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_263/src/current/fileop.c000044400626570001775000001076321041702132700176300ustar00cappsrsnperf00000000000000/* * Author: Don Capps * 3/13/2006 * Copyright: (2006) * You are free to distribute and use this benchmark, for free. * You are not permitted to distribute modified versions, or * borrow code from this project to create proprietary products * or competitive benchmarks. Any product that contains any * of this code will be considered a derivative work and will * be the sole property of me. * fileop [-f X ]|[-l # -u #] [-s Y] [-t] [-v] [-e] [-b] [-w] -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. -t # Verbose output option. -v # Version information. -e # Excel importable format. -b Output best case -w Output worst case * * 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 directorys, 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 #if defined(Windows) #include #endif int x,excel; int verbose = 0; int sz = 1; char *mbuffer; #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 _NUM_STATS 14 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_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 bzero(); void clear_stats(); #define THISVERSION " $Revision: 1.37 $" /*#define NULL 0*/ char version[]=THISVERSION; int cret; int lower, upper,range; int i; int best, worst; int main(int argc, char **argv) { if(argc == 1) { usage(); exit(1); } while((cret = getopt(argc,argv,"bwetvf:s:l:u: ")) != EOF){ switch(cret){ 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: File size is %d, Output is in Ops/sec. (A=Avg, B=Best, W=Worst)\n",sz); if(!verbose) { #ifdef Windows printf(" . %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %12s\n", "mkdir","rmdir","create","read","write","close","stat", "access","chmod","readdir","delete"," Total_files"); #else printf(" . %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %12s\n", "mkdir","rmdir","create","read","write","close","stat", "access","chmod","readdir","link ","unlink","delete", " Total_files"); #endif } if(x==0) x=1; if(range==0) lower=upper=x; for(i=lower;i<=upper;i++) { clear_stats(); x=i; /* * Dir Create test */ 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 delete test */ 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 */ 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 */ 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 */ file_read(x); if(verbose) { 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 %6.0f ",'A',x,stats[_STAT_DIR_CREATE].counter/stats[_STAT_DIR_CREATE].total_time); printf("%6.0f ",stats[_STAT_DIR_DELETE].counter/stats[_STAT_DIR_DELETE].total_time); printf("%6.0f ",stats[_STAT_CREATE].counter/stats[_STAT_CREATE].total_time); printf("%6.0f ",stats[_STAT_READ].counter/stats[_STAT_READ].total_time); printf("%6.0f ",stats[_STAT_WRITE].counter/stats[_STAT_WRITE].total_time); printf("%6.0f ",stats[_STAT_CLOSE].counter/stats[_STAT_CLOSE].total_time); printf("%6.0f ",stats[_STAT_STAT].counter/stats[_STAT_STAT].total_time); printf("%6.0f ",stats[_STAT_ACCESS].counter/stats[_STAT_ACCESS].total_time); printf("%6.0f ",stats[_STAT_CHMOD].counter/stats[_STAT_CHMOD].total_time); printf("%6.0f ",stats[_STAT_READDIR].counter/stats[_STAT_READDIR].total_time); #ifndef Windows printf("%6.0f ",stats[_STAT_LINK].counter/stats[_STAT_LINK].total_time); printf("%6.0f ",stats[_STAT_UNLINK].counter/stats[_STAT_UNLINK].total_time); #endif printf("%6.0f ",stats[_STAT_DELETE].counter/stats[_STAT_DELETE].total_time); printf("%12d ",x*x*x); printf("\n"); fflush(stdout); if(best) { printf("%c %4d %6.0f ",'B',x, 1/stats[_STAT_DIR_CREATE].best); printf("%6.0f ",1/stats[_STAT_DIR_DELETE].best); printf("%6.0f ",1/stats[_STAT_CREATE].best); printf("%6.0f ",1/stats[_STAT_READ].best); printf("%6.0f ",1/stats[_STAT_WRITE].best); printf("%6.0f ",1/stats[_STAT_CLOSE].best); printf("%6.0f ",1/stats[_STAT_STAT].best); printf("%6.0f ",1/stats[_STAT_ACCESS].best); printf("%6.0f ",1/stats[_STAT_CHMOD].best); printf("%6.0f ",1/stats[_STAT_READDIR].best); #ifndef Windows printf("%6.0f ",1/stats[_STAT_LINK].best); printf("%6.0f ",1/stats[_STAT_UNLINK].best); #endif printf("%6.0f ",1/stats[_STAT_DELETE].best); printf("%12d ",x*x*x); printf("\n"); fflush(stdout); } if(worst) { printf("%c %4d %6.0f ",'W',x, 1/stats[_STAT_DIR_CREATE].worst); printf("%6.0f ",1/stats[_STAT_DIR_DELETE].worst); printf("%6.0f ",1/stats[_STAT_CREATE].worst); printf("%6.0f ",1/stats[_STAT_READ].worst); printf("%6.0f ",1/stats[_STAT_WRITE].worst); printf("%6.0f ",1/stats[_STAT_CLOSE].worst); printf("%6.0f ",1/stats[_STAT_STAT].worst); printf("%6.0f ",1/stats[_STAT_ACCESS].worst); printf("%6.0f ",1/stats[_STAT_CHMOD].worst); printf("%6.0f ",1/stats[_STAT_READDIR].worst); #ifndef Windows printf("%6.0f ",1/stats[_STAT_LINK].worst); printf("%6.0f ",1/stats[_STAT_UNLINK].worst); #endif printf("%6.0f ",1/stats[_STAT_DELETE].worst); printf("%12d ",x*x*x); printf("\n"); fflush(stdout); } } } return(0); } void dir_create(int x) { int i,j; 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; chdir(buf); for(j=0;j stats[_STAT_DIR_CREATE].worst) stats[_STAT_DIR_CREATE].worst=stats[_STAT_DIR_CREATE].speed; chdir(buf); chdir(".."); } chdir(".."); } } void file_create(int x) { int i,j,k; int fd; int ret; char buf[100]; 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(); 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; } chdir(".."); } 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; } chdir(".."); } 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; } chdir(".."); } 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; } chdir(".."); } 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); } chdir(".."); } 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; } chdir(".."); } 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; } chdir(".."); } chdir(".."); } } void dir_delete(int x) { int i,j; 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; } chdir(".."); sprintf(buf,"iozone_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; } chdir(".."); sprintf(buf,"iozone_L1_%d_L2_%d",i,j); rmdir(buf); } chdir(".."); sprintf(buf,"iozone_L1_%d",i); rmdir(buf); } } void file_read(int x) { int i,j,k,y,fd; char buf[100]; stats[_STAT_READ].best=(double)99999.9; stats[_STAT_READ].worst=(double)0.00000000; for(i=0;i stats[_STAT_READ].worst) stats[_STAT_READ].worst=stats[_STAT_READ].speed; } chdir(".."); } 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] [-t] [-v] [-e] [-b] -[w]\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.\n"); printf(" -t # Verbose output option.\n"); printf(" -v # Version information.\n"); printf(" -e # Excel importable format.\n"); printf(" -b Output best case results\n"); printf(" -w Output worst case results\n"); printf("\n"); printf(" The structure of the file tree is:\n"); printf(" X number of Level 1 directorys, 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++) bzero((char *)&stats[i],sizeof(struct stat_struct)); } iozone3_263/docs/iozone.1000044400626570001775000000407501041702133000162410ustar00cappsrsnperf00000000000000.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\-+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] .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 VxFS VX_DIRECT for all file operations. Tells the VXFS filesystem that all operations to the file are to bypass the buffer cache and go directly to disk. .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'ss 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'ss 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 \-+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. .SH AUTHOR Original Author: William D. Norcott. wnorcott@us.oracle.com Features & extensions: Don Capps capps@iozone.org iozone3_263/src/current/makefile000044400626570001775000001166271041702132700177120ustar00cappsrsnperf00000000000000# # Version $Revision: 1.103 $ # # 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 = all: @echo "" @echo "You must specify the target. " @echo " -> AIX (32bit) <-" @echo " -> AIX-LF (32bit) <-" @echo " -> bsdi (32bit) <-" @echo " -> convex (32bit) <-" @echo " -> CrayX1 (32bit) <-" @echo " -> freebsd (32bit) <-" @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 (32bit) <-" @echo " -> netbsd (32bit) <-" @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 " -> Solaris10gcc (32bit) <-" @echo " -> sppux (32bit) <-" @echo " -> sppux-10.1 (32bit) <-" @echo " -> sppux_no_ansi-10.1 (32bit) <-" @echo " -> TRU64 (64bit) <-" @echo " -> UWIN (32bit) <-" @echo " -> Windows (95/98/NT) (32bit) <-" @echo "" clean: rm -f *.o iozone fileop 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 $(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 # # 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 $(CC) -O3 $(LDFLAGS) iozone_linux.o libasync.o libbif.o -lpthread \ -lrt -o iozone $(CC) -O3 -Dlinux fileop_linux.o -o fileop # # 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 $(CC) -O3 $(LDFLAGS) iozone_linux-powerpc.o libasync.o \ libbif.o -lpthread -lrt -o iozone $(CC) -O3 -Dlinux fileop_linux-ppc.o -o fileop # # GNU 'C' compiler Linux build for sparc chip with threads, largefiles, async I/O # linux-sparc: iozone_linux-sparc.o libbif.o libasync.o $(CC) -O3 $(LDFLAGS) iozone_linux-sparc.o libasync.o libbif.o \ -lpthread -lrt -o iozone # # 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 $(CC) -O3 $(LDFLAGS) iozone_linux-ia64.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O3 -Dlinux fileop_linux-ia64.o -o fileop # # 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 $(CC) -O3 -Dunix -DHAVE_ANSIC_C -DSHARED_MEM -DASYNC_IO \ -D_LARGEFILE64_SOURCE -Dlinux \ iozone_linux-powerpc64.o libasync.o libbif.o -lpthread \ -lrt -o iozone $(CC) -O3 -Dlinux fileop_linux-ppc64.o -o fileop # # GNU 'C' compiler Linux build with threads, largefiles, async I/O # linux-arm: iozone_linux-arm.o libbif.o libasync.o $(CC) -O3 $(LDFLAGS) iozone_linux-arm.o libbif.o libasync.o \ -lrt -lpthread -o iozone # # 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 $(CC) -O3 $(LDFLAGS) iozone_linux-AMD64.o libbif.o libasync.o \ -lrt -lpthread -o iozone $(CC) -O3 -Dlinux fileop_linux-AMD64.o -o fileop # # GNU 'C' compiler Linux build with S/390, threads, largfiles, async I/O # linux-S390: iozone_linux-s390.o libbif.o libasync.o $(CC) -O2 $(LDFLAGS) -lpthread -lrt iozone_linux-s390.o \ libbif.o libasync.o -o iozone # # GNU 'C' compiler Linux build with S/390, threads, largfiles, async I/O # linux-S390X: iozone_linux-s390x.o libbif.o libasync.o $(CC) -O2 $(LDFLAGS) -lpthread -lrt iozone_linux-s390x.o \ libbif.o libasync.o -o iozone # # 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_linux-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 $(CC) -O $(LDFLAGS) iozone_AIX-LF.o libbif.o \ -lpthreads -o iozone $(CC) -O fileop_AIX-LF.o -o fileop # # 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 $(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 # # 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 # Solaris10gcc: iozone_solaris10gcc.o libasync10.o libbif10.o fileop_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 # # 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/VRTSxfs/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 $(GCC) -O $(LDFLAGS) iozone_windows.o libbif.o -o iozone $(GCC) -O $(LDFLAGS) fileop_windows.o -o fileop # # 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 $(CC) -O $(LDFLAGS) iozone_bsdi.o libbif.o -o iozone $(CC) -O fileop_bsdi.o -o fileop # # GNU C compiler FreeBSD build with no threads, no largefiles, no async I/O # freebsd: iozone_freebsd.o libbif.o fileop_freebsd.o $(CC) $(LDFLAGS) iozone_freebsd.o libbif.o -o iozone $(CC) -O fileop_freebsd.o -o fileop # # GNU C compiler MacosX build with no threads, no largefiles, no async I/O # macosx: iozone_macosx.o libbif.o fileop_macosx.o $(CC) -O $(LDFLAGS) iozone_macosx.o libbif.o -o iozone $(CC) -O fileop_macosx.o -o fileop # # # GNU C compiler OpenBSD build with no threads, no largefiles, no async I/O # openbsd: iozone_openbsd.o libbif.o fileop_openbsd.o $(CC) -O $(LDFLAGS) iozone_openbsd.o libbif.o -o iozone $(CC) -O fileop_openbsd.o -o fileop # # 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 no threads, no largefiles, no async I/O # netbsd: iozone_netbsd.o libbif.o fileop_netbsd.o $(CC) -O $(LDFLAGS) iozone_netbsd.o libbif.o -o iozone $(CC) -O fileop_netbsd.o -o fileop # # # 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 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 \ -o iozone_linux-powerpc64.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-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) -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) -Wall -c -O3 -Dunix -DHAVE_ANSIC_C -DASYNC_IO -D_LARGEFILE64_SOURCE \ -DSHARED_MEM -Dlinux $(CFLAGS) libbif.c -o libbif.o $(CC) -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_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_netbsd.o: fileop.c @echo "" @echo "Building fileop for NetBSD" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_netbsd.o fileop_Solaris.o: fileop.c @echo "" @echo "Building fileop for Solaris" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_Solaris.o fileop_Solaris10gcc.o: fileop.c @echo "" @echo "Building fileop for Solaris10gcc" @echo "" $(CC) -c -O $(CFLAGS) fileop.c -o fileop_Solaris10gcc.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 -O $(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) 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_windows.o: fileop.c @echo "" @echo "Building fileop for Windows" @echo "" $(GCC) -Wall -c -O3 $(CFLAGS) -DWindows fileop.c -o fileop_windows.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_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 \ $(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_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_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 # # -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 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 @echo "" @echo "Build iozone for FreeBSD" @echo "" $(CC) -c ${CFLAGS} -Dunix -Dbsd4_2 -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"freebsd"' -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_freebsd.o $(CC) -c ${CFLAGS} -Dunix -Dbsd4_2 -DHAVE_ANSIC_C -DNO_THREADS \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone_macosx.o: iozone.c libbif.c @echo "" @echo "Build iozone for MacOSX" @echo "" $(CC) -c -O -Dunix -Dbsd4_2 -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"macosx"' -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_macosx.o $(CC) -c -O -Dunix -Dbsd4_2 -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 -Dbsd4_4 -DHAVE_ANSIC_C -DNO_THREADS \ -DNAME='"netbsd"' -DSHARED_MEM $(CFLAGS) iozone.c -o iozone_netbsd.o $(CC) -c -O -Dunix -Dbsd4_4 -DHAVE_ANSIC_C -DNO_THREADS \ -DSHARED_MEM $(CFLAGS) libbif.c -o libbif.o iozone3_263/src/current/libasync.c000044400626570001775000001207661041702133000201530ustar00cappsrsnperf00000000000000 /* * Library for Posix async read operations with hints. * Author: Don Capps * Company: Hewlett Packard * 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(solaris) || defined(linux) || defined(SCO_Unixware_gcc) #else #include #endif #include #include #include #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__)) /* 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 void mbcopy(char *source, char *dest, size_t len); #if !defined(solaris) && !defined(off64_t) && !defined(_OFF64_T) && !defined(__off64_t_defined) && !defined(SCO_Unixware_gcc) typedef long long off64_t; #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. */ char version[] = "Libasync Version $Revision: 3.19 $"; struct cache_ent { struct aiocb myaiocb; /* For use in small file mode */ #ifdef _LARGEFILE64_SOURCE #if defined(__CrayX1__) aiocb64_t myaiocb64; /* For use in large file mode */ #else struct aiocb64 myaiocb64; /* For use in large file mode */ #endif #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; struct cache_ent *alloc_cache(); struct cache_ent *incache(); void async_init(); void end_async(); int async_read(); void takeoff_cache(); void del_cache(); void async_release(); void putoninuse(); void takeoffinuse(); 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(); /* 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 */ /***********************************************/ void async_init(gc,fd,flag) struct cache **gc; int fd; int flag; { #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 */ /***********************************************/ void end_async(gc) struct cache *gc; { del_cache(gc); async_write_finish(gc); free((void *)gc); } /************************************************************************* * 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. *************************************************************************/ 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; { 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))) { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) #else while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS) #endif #else while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) #endif { ; } if(ret) { printf("aio_error 1: ret %d %d\n",ret,errno); } #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ retval=aio_return(&ce->myaiocb); #else #if defined(__CrayX1__) retval=aio_return64((aiocb64_t *)&ce->myaiocb64); #else retval=aio_return64((struct aiocb64 *)&ce->myaiocb64); #endif #endif #else retval=aio_return(&ce->myaiocb); #endif if(retval > 0) { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ mbcopy((char *)ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval); #else mbcopy((char *)ce->myaiocb64.aio_buf,(char *)ubuffer,(size_t)retval); #endif #else mbcopy((char *)ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval); #endif } #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(retval < ce->myaiocb.aio_nbytes) #else if(retval < ce->myaiocb64.aio_nbytes) #endif #else if(retval < ce->myaiocb.aio_nbytes) #endif { printf("aio_return error1: ret %d %d\n",retval,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_return error1: fd %d offset %ld buffer %lx size %d Opcode %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode #else printf("aio_return error1: fd %d offset %lld buffer %lx size %d Opcode %d\n", ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_offset, (long)(ce->myaiocb64.aio_buf), ce->myaiocb64.aio_nbytes, ce->myaiocb64.aio_lio_opcode #endif #else printf("aio_return error1: fd %d offset %d buffer %lx size %d Opcode %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode #endif ); } 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: #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ret=aio_read(&first_ce->myaiocb); #else ret=aio_read64(&first_ce->myaiocb64); #endif #else ret=aio_read(&first_ce->myaiocb); #endif if(ret!=0) { if(errno==EAGAIN) goto again; else printf("error returned from aio_read(). Ret %d 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); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ret=aio_read(&ce->myaiocb); #else ret=aio_read64(&ce->myaiocb64); #endif #else ret=aio_read(&ce->myaiocb); #endif if(ret!=0) { takeoff_cache(gc,ce); break; } } out: if(del_read) /* Wait for the first read to complete */ { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) #else while((ret=aio_error64(&first_ce->myaiocb64))== EINPROGRESS) #endif #else while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) #endif { ; } if(ret) printf("aio_error 2: ret %d %d\n",ret,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ retval=aio_return(&first_ce->myaiocb); #else retval=aio_return64(&first_ce->myaiocb64); #endif #else retval=aio_return(&first_ce->myaiocb); #endif #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(retval < first_ce->myaiocb.aio_nbytes) #else if(retval < first_ce->myaiocb64.aio_nbytes) #endif #else if(retval < first_ce->myaiocb.aio_nbytes) #endif { printf("aio_return error2: ret %d %d\n",retval,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_return error2: fd %d offset %lld buffer %lx size %d Opcode %d\n", first_ce->myaiocb.aio_fildes, first_ce->myaiocb.aio_offset, (long)(first_ce->myaiocb.aio_buf), first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode #else printf("aio_return error2: fd %d offset %lld buffer %lx size %d Opcode %d\n", first_ce->myaiocb64.aio_fildes, first_ce->myaiocb64.aio_offset, (long)(first_ce->myaiocb64.aio_buf), first_ce->myaiocb64.aio_nbytes, first_ce->myaiocb64.aio_lio_opcode #endif #else printf("aio_return error2: fd %d offset %d buffer %lx size %d Opcode %d\n", first_ce->myaiocb.aio_fildes, first_ce->myaiocb.aio_offset, (long)(first_ce->myaiocb.aio_buf), first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode #endif ); } if(retval > 0) { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval); #else mbcopy((char *)first_ce->myaiocb64.aio_buf,(char *)ubuffer,(size_t)retval); #endif #else mbcopy((char *)first_ce->myaiocb.aio_buf,(char *)ubuffer,(size_t)retval); #endif } 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. ************************************************************************/ struct cache_ent * alloc_cache(gc,fd,offset,size,op) struct cache *gc; long long fd,size,op; off64_t offset; { struct cache_ent *ce; long 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)); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off64_t)offset; ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb.aio_buf=(volatile void *)temp; if(ce->myaiocb.aio_buf == 0) #else ce->myaiocb64.aio_fildes=(int)fd; ce->myaiocb64.aio_offset=(off64_t)offset; ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb64.aio_buf=(volatile void *)temp; if(ce->myaiocb64.aio_buf == 0) #endif #else ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off_t)offset; ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb.aio_buf=(volatile void *)temp; if(ce->myaiocb.aio_buf == 0) #endif { printf("Malloc failed\n"); exit(176); } /*bzero(ce->myaiocb.aio_buf,(size_t)size);*/ #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ 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; #else ce->myaiocb64.aio_reqprio=0; ce->myaiocb64.aio_nbytes=(size_t)size; ce->myaiocb64.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb64.aio_lio_opcode=(int)op; #endif #else 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; #endif 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. *************************************************************************/ struct cache_ent * incache(gc,fd,offset,size) struct cache *gc; long long fd,size; off64_t offset; { struct cache_ent *move; if(gc->head==0) { return(0); } move=gc->head; #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ 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; } #else while(move) { if((move->fd == fd) && (move->myaiocb64.aio_offset==(off64_t)offset) && ((size_t)size==move->myaiocb64.aio_nbytes)) { return(move); } move=move->forward; } #endif #else while(move) { if((move->fd == fd) && (move->myaiocb.aio_offset==(off_t)offset) && ((size_t)size==move->myaiocb.aio_nbytes)) { return(move); } move=move->forward; } #endif 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(gc,ce) 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) { free((void *)(ce->real_address)); free((void *)ce); } 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) { free((void *)(ce->real_address)); free((void *)ce); } 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. ************************************************************************/ void del_cache(gc) struct cache *gc; { struct cache_ent *ce; ssize_t ret; ce=gc->head; while(1) { ce=gc->head; if(ce==0) return; #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED) #else while((ret = aio_cancel64(0,&ce->myaiocb64))==AIO_NOTCANCELED) #endif #else while((ret = aio_cancel(0,&ce->myaiocb))==AIO_NOTCANCELED) #endif ; #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ret = aio_return(&ce->myaiocb); #else ret = aio_return64(&ce->myaiocb64); #endif #else ret = aio_return(&ce->myaiocb); #endif 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. ************************************************************************/ 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; { 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))) { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) #else while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS) #endif #else while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) #endif { ; } if(ret) printf("aio_error 3: ret %d %d\n",ret,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(ce->oldbuf != ce->myaiocb.aio_buf || ce->oldfd != ce->myaiocb.aio_fildes || ce->oldsize != ce->myaiocb.aio_nbytes) #else if(ce->oldbuf != ce->myaiocb64.aio_buf || ce->oldfd != ce->myaiocb64.aio_fildes || ce->oldsize != ce->myaiocb64.aio_nbytes) #endif #else if(ce->oldbuf != ce->myaiocb.aio_buf || ce->oldfd != ce->myaiocb.aio_fildes || ce->oldsize != ce->myaiocb.aio_nbytes) #endif printf("It changed in flight\n"); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ retval=aio_return(&ce->myaiocb); #else retval=aio_return64(&ce->myaiocb64); #endif #else retval=aio_return(&ce->myaiocb); #endif if(retval > 0) { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ *ubuffer=(char *)ce->myaiocb.aio_buf; #else *ubuffer=(char *)ce->myaiocb64.aio_buf; #endif #else *ubuffer=(char *)ce->myaiocb.aio_buf; #endif }else *ubuffer=0; #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(retval < ce->myaiocb.aio_nbytes) #else if(retval < ce->myaiocb64.aio_nbytes) #endif #else if(retval < ce->myaiocb.aio_nbytes) #endif { printf("aio_return error4: ret %d %d\n",retval,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_return error4: fd %d offset %lld buffer %lx size %d Opcode %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode #else printf("aio_return error4: fd %d offset %lld buffer %lx size %d Opcode %d\n", ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_offset, (long)(ce->myaiocb64.aio_buf), ce->myaiocb64.aio_nbytes, ce->myaiocb64.aio_lio_opcode #endif #else printf("aio_return error4: fd %d offset %d buffer %lx size %d Opcode %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_nbytes, ce->myaiocb.aio_lio_opcode #endif ); } 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: #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ 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); #else first_ce->oldbuf=first_ce->myaiocb64.aio_buf; first_ce->oldfd=first_ce->myaiocb64.aio_fildes; first_ce->oldsize=first_ce->myaiocb64.aio_nbytes; ret=aio_read64(&first_ce->myaiocb64); #endif #else 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); #endif if(ret!=0) { if(errno==EAGAIN) goto again; else printf("error returned from aio_read(). Ret %d 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); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ce->oldbuf=ce->myaiocb.aio_buf; ce->oldfd=ce->myaiocb.aio_fildes; ce->oldsize=ce->myaiocb.aio_nbytes; ret=aio_read(&ce->myaiocb); #else ce->oldbuf=ce->myaiocb64.aio_buf; ce->oldfd=ce->myaiocb64.aio_fildes; ce->oldsize=ce->myaiocb64.aio_nbytes; ret=aio_read64(&ce->myaiocb64); #endif #else ce->oldbuf=ce->myaiocb.aio_buf; ce->oldfd=ce->myaiocb.aio_fildes; ce->oldsize=ce->myaiocb.aio_nbytes; ret=aio_read(&ce->myaiocb); #endif if(ret!=0) { takeoff_cache(gc,ce); break; } } out: if(del_read) /* Wait for the first read to complete */ { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) #else while((ret=aio_error64(&first_ce->myaiocb64))== EINPROGRESS) #endif #else while((ret=aio_error(&first_ce->myaiocb))== EINPROGRESS) #endif { ; } if(ret) printf("aio_error 4: ret %d %d\n",ret,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ 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); #else if(first_ce->oldbuf != first_ce->myaiocb64.aio_buf || first_ce->oldfd != first_ce->myaiocb64.aio_fildes || first_ce->oldsize != first_ce->myaiocb64.aio_nbytes) printf("It changed in flight2\n"); retval=aio_return64(&first_ce->myaiocb64); #endif #else 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); #endif #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ if(retval < first_ce->myaiocb.aio_nbytes) #else if(retval < first_ce->myaiocb64.aio_nbytes) #endif #else if(retval < first_ce->myaiocb.aio_nbytes) #endif { printf("aio_return error5: ret %d %d\n",retval,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_return error5: fd %d offset %lld buffer %lx size %d Opcode %d\n", first_ce->myaiocb.aio_fildes, first_ce->myaiocb.aio_offset, (long)(first_ce->myaiocb.aio_buf), first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode #else printf("aio_return error5: fd %d offset %lld buffer %lx size %d Opcode %d\n", first_ce->myaiocb64.aio_fildes, first_ce->myaiocb64.aio_offset, (long)(first_ce->myaiocb64.aio_buf), first_ce->myaiocb64.aio_nbytes, first_ce->myaiocb64.aio_lio_opcode #endif #else printf("aio_return error5: fd %d offset %ld buffer %lx size %d Opcode %d\n", first_ce->myaiocb.aio_fildes, first_ce->myaiocb.aio_offset, (long)(first_ce->myaiocb.aio_buf), first_ce->myaiocb.aio_nbytes, first_ce->myaiocb.aio_lio_opcode #endif ); } if(retval > 0) { #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ *ubuffer=(char *)first_ce->myaiocb.aio_buf; #else *ubuffer=(char *)first_ce->myaiocb64.aio_buf; #endif #else *ubuffer=(char *)first_ce->myaiocb.aio_buf; #endif }else *ubuffer=(char *)0; 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. ************************************************************************/ void async_release(gc) struct cache *gc; { 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. ************************************************************************/ void putoninuse(gc,entry) struct cache *gc; struct cache_ent *entry; { 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. ************************************************************************/ void takeoffinuse(gc) struct cache *gc; { 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"); free((void*)(ce->real_address)); free(ce); } /************************************************************************* * 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. * *************************************************************************/ 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; { 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 */ #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ mbcopy(buffer,(char *)(ce->myaiocb.aio_buf),(size_t)size); #else mbcopy(buffer,(char *)(ce->myaiocb64.aio_buf),(size_t)size); #endif #else mbcopy(buffer,(char *)(ce->myaiocb.aio_buf),(size_t)size); #endif async_put_on_write_queue(gc,ce); /* printf("asw: fd %d offset %lld, size %d\n",ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_offset, ce->myaiocb64.aio_nbytes); */ again: #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ret=aio_write(&ce->myaiocb); #else ret=aio_write64(&ce->myaiocb64); #endif #else ret=aio_write(&ce->myaiocb); #endif 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 %d errno %d count %lld\n",ret,errno,gc->w_count); /* printf("aio_write_no_copy: fd %d buffer %x offset %lld size %d\n", ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_buf, ce->myaiocb64.aio_offset, ce->myaiocb64.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. *************************************************************************/ 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; { struct cache_ent *ce; long 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)); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off64_t)offset; if(!direct) { ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(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) #else ce->myaiocb64.aio_fildes=(int)fd; ce->myaiocb64.aio_offset=(off64_t)offset; if(!direct) { ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(page_size-1); ce->myaiocb64.aio_buf=(volatile void *)temp; } else { ce->myaiocb64.aio_buf=(volatile void *)buffer; ce->real_address=(char *)free_addr; } if(ce->myaiocb64.aio_buf == 0) #endif #else ce->myaiocb.aio_fildes=(int)fd; ce->myaiocb.aio_offset=(off_t)offset; if(!direct) { ce->real_address = (char *)malloc((size_t)(size+page_size)); temp=(long)ce->real_address; temp = (temp+page_size) & ~(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) #endif { printf("Malloc failed 2\n"); exit(180); } #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ 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; #else ce->myaiocb64.aio_reqprio=0; ce->myaiocb64.aio_nbytes=(size_t)size; ce->myaiocb64.aio_sigevent.sigev_notify=SIGEV_NONE; ce->myaiocb64.aio_lio_opcode=(int)op; #endif #else 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; #endif ce->fd=(int)fd; return(ce); } /************************************************************************* * Put it on the outbound queue. *************************************************************************/ void async_put_on_write_queue(gc,ce) struct cache *gc; struct cache_ent *ce; { 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 *************************************************************************/ void async_write_finish(gc) struct cache *gc; { while(gc->w_head) { /*printf("async_write_finish: Waiting for buffer %x to finish\n",gc->w_head->myaiocb64.aio_buf);*/ async_wait_for_write(gc); } } /************************************************************************* * Wait for an I/O to finish *************************************************************************/ void async_wait_for_write(gc) struct cache *gc; { struct cache_ent *ce; size_t ret,retval; if(gc->w_head==0) return; ce=gc->w_head; gc->w_head=ce->forward; gc->w_count--; ce->forward=0; if(ce==gc->w_tail) gc->w_tail=0; /*printf("Wait for buffer %x offset %lld size %d to finish\n", ce->myaiocb64.aio_buf, ce->myaiocb64.aio_offset, ce->myaiocb64.aio_nbytes); printf("write count %lld \n",gc->w_count); */ #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) #else while((ret=aio_error64(&ce->myaiocb64))== EINPROGRESS) #endif #else while((ret=aio_error(&ce->myaiocb))== EINPROGRESS) #endif { ; } if(ret) { printf("aio_error 5: ret %d %d\n",ret,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("fd %d offset %lld size %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); #else printf("fd %d offset %lld size %d\n", ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_offset, ce->myaiocb64.aio_nbytes); #endif #else printf("fd %d offset %lld size %d\n", ce->myaiocb.aio_fildes, ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); #endif exit(181); } #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ retval=aio_return(&ce->myaiocb); #else #if defined(__CrayX1__) retval=aio_return64((aiocb64_t *)&ce->myaiocb64); #else retval=aio_return64((struct aiocb64 *)&ce->myaiocb64); #endif #endif #else retval=aio_return(&ce->myaiocb); #endif if((int)retval < 0) { printf("aio_return error: %d\n",errno); } if(!ce->direct) { /* printf("Freeing buffer %x\n",ce->real_address);*/ free((void *)(ce->real_address)); free((void *)ce); } } /************************************************************************* * 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. * *************************************************************************/ size_t async_write_no_copy(gc,fd,buffer,size,offset,depth,free_addr) struct cache *gc; long long fd,size; char *buffer; off64_t offset; long long depth; char *free_addr; { 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 %d\n",ce->myaiocb64.aio_fildes, ce->myaiocb64.aio_offset, ce->myaiocb64.aio_nbytes); */ again: #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ ret=aio_write(&ce->myaiocb); #else ret=aio_write64(&ce->myaiocb64); #endif #else ret=aio_write(&ce->myaiocb); #endif 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 %d errno %d\n",ret,errno); #ifdef _LARGEFILE64_SOURCE #ifdef __LP64__ printf("aio_write_no_copy: fd %d buffer %lx offset %lld size %d\n", ce->myaiocb.aio_fildes, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); #else printf("aio_write_no_copy: fd %d buffer %lx offset %lld size %d\n", ce->myaiocb64.aio_fildes, (long)(ce->myaiocb64.aio_buf), ce->myaiocb64.aio_offset, ce->myaiocb64.aio_nbytes); #endif #else printf("aio_write_no_copy: fd %d buffer %lx offset %ld size %d\n", ce->myaiocb.aio_fildes, (long)(ce->myaiocb.aio_buf), ce->myaiocb.aio_offset, ce->myaiocb.aio_nbytes); #endif exit(182); } } else { return((ssize_t)size); } } void mbcopy(source, dest, len) char *source,*dest; size_t len; { int i; for(i=0;i #include #include #ifdef __AIX__ #include #else #include #endif #if defined(OSV5) || defined(linux) || defined (__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__) #include #endif #if defined(linux) #include #include #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 #include #include #include #endif /* Little Endian */ #define ENDIAN_1 1 /* Big Endian */ #define ENDIAN_2 2 /* Middle Endian */ #define ENDIAN_3 3 #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.15 $"; void do_eof(int ); /* Used internally */ void do_header(int ); /* Used internally */ int endian(void); #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; }; /* * Write the EOF and close the file */ #ifdef HAVE_ANSIC_C void close_xls(int fd) { #else 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; 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; 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"); } write(fd,&floatrec,11); /* Don't write floatrec. Padding problems */ 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); 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}; 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; unsigned char *c,c1,c2,c3,c4,c5,c6,c7,c8; c=(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); return(-1); } iozone3_263/src/current/gnuplot.dem000044400626570001775000000031341041702133000203470ustar00cappsrsnperf00000000000000# # $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_263/src/current/gengnuplot.sh000055100626570001775000000052231041702133000207060ustar00cappsrsnperf00000000000000#!/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_263/src/current/Generate_Graphs000055100626570001775000000013771041702133000211570ustar00cappsrsnperf00000000000000# # 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_263/src/current/gnu3d.dem000055100626570001775000000171531041702133000177040ustar00cappsrsnperf00000000000000# # $Id: 3D plot of performance # # Processes files that were created by Generate_Graphs # and displays the results. Also, saves a postscript copy. # # Don Capps set terminal x11 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 autoscale z set xrange [2.**5:2.**24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'write/iozone_gen_out.gnuplot' title "Write performance" set terminal postscript color set output "write/write.ps" splot 'write/iozone_gen_out.gnuplot' title "Write performance" pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'rewrite/iozone_gen_out.gnuplot' using 1:2:3 title "ReWrite performance" with lines set terminal postscript color set output "rewrite/rewrite.ps" splot 'rewrite/iozone_gen_out.gnuplot' using 1:2:3 title "ReWrite performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'read/iozone_gen_out.gnuplot' using 1:2:3 title "Read performance" with lines set terminal postscript color set output "read/read.ps" splot 'read/iozone_gen_out.gnuplot' using 1:2:3 title "Read performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'reread/iozone_gen_out.gnuplot' using 1:2:3 title "Reread performance" with lines set terminal postscript color set output "reread/reread.ps" splot 'reread/iozone_gen_out.gnuplot' using 1:2:3 title "Reread performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'randread/iozone_gen_out.gnuplot' using 1:2:3 title "Random read performance" with lines set terminal postscript color set output "randread/randread.ps" splot 'randread/iozone_gen_out.gnuplot' using 1:2:3 title "Random read performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'randwrite/iozone_gen_out.gnuplot' using 1:2:3 title "Random write performance" with lines set terminal postscript color set output "randwrite/randwrite.ps" splot 'randwrite/iozone_gen_out.gnuplot' using 1:2:3 title "Random write performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'bkwdread/iozone_gen_out.gnuplot' using 1:2:3 title "Read Backwards performance" with lines set terminal postscript color set output "bkwdread/bkwdread.ps" splot 'bkwdread/iozone_gen_out.gnuplot' using 1:2:3 title "Read Backwards performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'recrewrite/iozone_gen_out.gnuplot' using 1:2:3 title "Record rewrite performance" with lines set terminal postscript color set output "recrewrite/recrewrite.ps" splot 'recrewrite/iozone_gen_out.gnuplot' using 1:2:3 title "Record rewrite performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'strideread/iozone_gen_out.gnuplot' using 1:2:3 title "Stride read performance" with lines set terminal postscript color set output "strideread/strideread.ps" splot 'strideread/iozone_gen_out.gnuplot' using 1:2:3 title "Stride read performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'fwrite/iozone_gen_out.gnuplot' using 1:2:3 title "Fwrite performance" with lines set terminal postscript color set output "fwrite/fwrite.ps" splot 'fwrite/iozone_gen_out.gnuplot' using 1:2:3 title "Fwrite performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'frewrite/iozone_gen_out.gnuplot' using 1:2:3 title "Frewrite performance" with lines set terminal postscript color set output "frewrite/frewrite.ps" splot 'frewrite/iozone_gen_out.gnuplot' using 1:2:3 title "Frewrite performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'fread/iozone_gen_out.gnuplot' using 1:2:3 title "Fread performance" with lines set terminal postscript color set output "fread/fread.ps" splot 'fread/iozone_gen_out.gnuplot' using 1:2:3 title "Fread performance" with lines pause -1 "Hit return to continue" set terminal x11 set title "Iozone performance" set grid lt 2 lw 1 set surface set xtics set ytics set logscale x 2 set logscale y 2 set autoscale z set xrange [5:24] set xlabel "File size in 2^n KBytes" set ylabel "Record size in 2^n Kbytes" set zlabel "Kbytes/sec" set data style lines set dgrid3d 80,80,3 splot 'freread/iozone_gen_out.gnuplot' using 1:2:3 title "Freread performance" with lines set terminal postscript color set output "freread/freread.ps" splot 'freread/iozone_gen_out.gnuplot' using 1:2:3 title "Freread performance" with lines pause -1 "Hit return to exit" iozone3_263/src/current/Gnuplot.txt000055100626570001775000000013541041702133000203620ustar00cappsrsnperf00000000000000The 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_263/src/current/gnuplotps.dem000044400626570001775000000032251041702133000207130ustar00cappsrsnperf00000000000000# # $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_263/src/current/read_telemetry000044400626570001775000000011221041702133000211130ustar00cappsrsnperf00000000000000# # # 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_263/src/current/write_telemetry000044400626570001775000000011231041702133000213330ustar00cappsrsnperf00000000000000# # # 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_263/src/current/client_list000044400626570001775000000010531041702133000204220ustar00cappsrsnperf00000000000000# # Lines that start with # in column 0 are comments. # # Format: 3 fields, space delimited. # # client_name working_dir_on_client path_to_iozone_on_client # # Example: With two clients # # 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 # # 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 # iozone3_263/src/current/spec.in000044400626570001775000000037141041702132700174640ustar00cappsrsnperf00000000000000Summary: Iozone Filesystem Benchmark Name: iozone Version: 3 Release: 263 Copyright: 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_263/src/current ## ## BUILD ## %build make linux ## ## INSTALL ## %install mkdir -p $RPM_BUILD_ROOT/opt/iozone/bin cp $RPM_BUILD_DIR/iozone3_263/src/current/iozone $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_263/src/current/fileop $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_263/src/current/Generate_Graphs $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_263/src/current/gengnuplot.sh $RPM_BUILD_ROOT/opt/iozone/bin/ cp $RPM_BUILD_DIR/iozone3_263/src/current/gnu3d.dem $RPM_BUILD_ROOT/opt/iozone/bin/ mkdir -p $RPM_BUILD_ROOT/opt/iozone/docs cp $RPM_BUILD_DIR/iozone3_263/docs/IOzone_msword_98.pdf $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_263/docs/Run_rules.doc $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_263/docs/IOzone_msword_98.doc $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_263/docs/Iozone_ps.gz $RPM_BUILD_ROOT/opt/iozone/docs/ cp $RPM_BUILD_DIR/iozone3_263/src/current/Gnuplot.txt $RPM_BUILD_ROOT/opt/iozone/docs/ mkdir -p $RPM_BUILD_ROOT/opt/iozone/man/man1 cp $RPM_BUILD_DIR/iozone3_263/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_263/docs/IOzone_msword_98.pdf000064400626570001775000005144151041702133000204730ustar00cappsrsnperf00000000000000%PDF-1.2 %쏢 8 0 obj <> stream x]r+c¾"-[f96EdﹰUf^!-@hԖrUG*NwGoVޮ?̲,o~ϧcY/񛣰%\EGAʃru;e$~Y6DImB?/(c/o~]y(HOeFK/2T?_맮M{oSi}O<+wF/ _P,6|mr?+(Y҈z ;k]KLWH:SGR}jnW> C?U|vtq&^aR"CEH5(S5Mx慩DEQPWINJ,@_y?A'Oi$1b?{eX;QA fG/٘z:N zTc $NqؔVw\{z/,ˋn _F\Z6gJ >yqGqVk 8fHMu[ZgSW{|ctG:hFlĖێz9u3k~J0/9dْ' "ŅH+/J6+l:ASZ' nU(MEd V֫%9@o}2|ԝv]QLZ:!LT="?}58jl H9pLeݸp&92Mv\7_?嶴T=3=wzuiGf~8WljT9 lq@-ݢ/S`+nB!`EƦgn?K&8֡SPAXjHYpHHFbVj~ s;IQ '&Ō. fZ C{ضbo tp>w|Q{`jc둇= 6=-'cn-3326~Kԣ'k%S X& X̐Ս:~ɲelT؂50hI+ xthy3A?T[{FsA=6*6,͚ƀacU|$w8l4-{8XX#~'0kT7zD_{WPp$(ػhggm:j'GXBC0 I@)&Ox}Φm{"(t&4zաdg @b)ygta3Sk탮`0Vl\r^dl$2ظ;ό9[ 'Yn O@{ YeO܃)?ҳ}4i^e"HZqy̆&/쀶*Hbj5^'^/$; Qo9RD:Rkѡc&i/#8Kd5Vv DYgS8S0b] V5 ^/ .]v(Y!p{~ЖC=}%B\H }1^aաh0hG*e Bà"Rb#D%nӂ hia! =mz8[)_Twxb6c/M}Jlf8m`@i}xd5<~}Hq]I (^/vRK37Q%rfa E%< n~gc%'HqĵݠC.Rh 1F #y53r,)A= FR! s]L0#FZՍp]c&A4[ dP:ρME.T)`)gNp@8Er .IY=u@Yu|Y~C Ȍt)"#q`%L˲|d!DS14@nS$4-Rv  P{?t,U5АnGb&x鍊/t@t vU:JV"P6oev@7LZa6ϧ }b_!#Pu@}5(d-E nOPuT}2l:+QF&<5pU:&z`Z#W13Y6j6ۓ+`S?&j*_h>jOA/xTv< \<6dÂFǢ^Re{4ct6Y2i-#O"V~Qê`e$F*t,/]((9vLDlat :4o Jq7썆!8z8,(fg5=fgx(\ M,cIBwBw)@RV`̘Ӻ9MfpbY .GYjGFwUU(1}5rɦcGJr 砰]\%QLjDQ&[0bp%HyKv1 MdsZ  2AlHp9 tzpmR*谑6n3;.-񙶕kFspf<tKTu o8Y X +ΗNM\qg/[}6zqQ$IF!\,P~}Pyә{&}2 `mpy Tsa%;A{CMP2玒Qi!} a]Ma ~@#-a`R|/XcpnXvVtdc!0CDY[[כOɣʑ=ͤpQx5N9s+ ץӕt+.6FP^BOuޞ\k"(* A0Ҕ4 WT깦#i +#p B1TKe(~3~/g=/fs+- 0ʍZ:NM9|? "gAB*h4$+5ELw*B|@95" t'fs/(?澎ӕ[(/#Bga5{7ʉb%(ajVLB 9 ClC0*=o]6ᑛ:|.ߎËendstream endobj 9 0 obj 4054 endobj 18 0 obj <> stream x\ɒWfC,P=a[c /Cjt4_XvW{jA&B 5חMXfD\/]d(lӗ"$NB4_D<*1)՗\ԓ2.D-t}9_~~6q)Ңn#URG3!:ɪMֱLt>F$NSYV稊*yɪ-1hڥ&?;:֍y:]ww2gIӊX1S P!hc#**/sEYUR _(b5e5LGвUQMS{ը-S̅SFH;:(}géLĖ\!6|hFf"β^X #(2ܧHmy2ax8O]Q#9ʚ} ΄1I~?2sASHHu.p6;LkK`4mjuiegWkE'&j?SOڄ2\ؾA3=-Mg29bx( ]gFL, X@)Se ÞyWua Ӊ[HlkR=iۓwv̈@nZNwe5i zX"O>]drKIK`=IP Zzc$x.]-B]B1hlhN֕fZ ҕVD,+B[4kB4%sX b^r1nJ,o笘@ Ⱥ,VH3}g4Ώ GӘcD!s85Z*+[QHFQZQ` *)ɫi=I ,l%vN5ɸsCY&C̎↶'䦔mbL22}@OF{dit_!X>VF͍'RU 0ݳ$8::>Tcf#[&㵬yȖv;‰:Nq[,-_vMꩃmzY-z"F€O .I,yx-˹ny-xOgzυ <9^Xȉ׈ja=Ei]@ϙ.XE*cճt5NxqێOSY3vD[G$PˣPB]2O$#]ZW!dr3ސT(NV(άy' P(Ox^3a7 x/ `)KE^1nXt2h}$؀'8|8F+6IggD|9Coͮp Mmv PْGL?#HO}7 # &~:0<JSܲO -`g.F{.T~lGY>H2G 5^F _M+?yev}LͥM.7Jtq]y1jS* vu[Zt]+}<}CsuWlް1IDݦnLDznYL{?shyROsMI֝(feI:yAVuxO>*1K/+y\y|ٷ4mH, k!LP8/шEԫ'NvnEp5 +M6ˇhxNZh&_ЖZ,s$qVy ]7גt7!e9X/h]EJ d WO`m暆b]fuDhPUGٷڸRS_7p@9ݣ Nڵ>D?%FgJa'P yS/dENNj V!׈5#JTcd :T\/:扔N`TmnEw `^d&r &LA{C@𖩄?,<3rɬC.$?ҿ&.nªX;ZSOl { 4^@)YX.RE+j+YJ~ːݯAr9Pl2 uϴ@#%RLؑ|Kw*uXIddRD{\Ma>r=䁢d-H ; `ԟ9i"}h}ŚuH`slNMHf5)q'T@dCFמޱ2ؠhs"LqWՋ>&:/C Wj t&z~<'Xf  1 0v)goG&0녃 B58t2ZwmZfob<'U50D9+B.ǗPùMc7dFf;[43|rl',q_F[_Av>XޣigQwa@%Ne+UA`SPߟA=OeOφGm$ڏHNX#ctg׶a }<K:kP>d3r>i 8+nbl. /+I P@>znYBGp.͕>$rldliɣe?):C !ǧLc/͜_|ej! yj-a)%B0wѶ\GZ$& "(3 8I}TI7GX;X\$vˏ.:f{;n:·X z| }/@Ab]a%T%MWz_y/SLx0OӯD,G_{򍮀vh0s 瓿\,endstream endobj 19 0 obj 3159 endobj 22 0 obj <> stream x]r$ }W[4UVʼn+qbG)?yjdҬV?#o$!ĵ/ڞI6q書89zwnGIYU}~oxQ\oN8J_MQ]'*I4k67GǛ?3:$+7')U9}wmUI'ۓ:J؞QeE_mOmB]4v)%=lIQuhf'L'ܳïPsTwz,x?(ݔf:|76d<~{Gg"+1y=˼{j'ۤɨ'bwMvݒ5{{*Oژ z]sfAZi+yk_WT96kZ .}nţ"c"~fc?7ӓAL.9۬,4YysIo?b.ܣG &MTJ@htֺhEqžz)x$v,{ $M~m+pH[N!E] UT&RXQڋTsh؝g Ws%_mѐv7JS^Es 5 s8g{";xAe;CUvGcg@WO-Is a˥č$Pv pln|,a8M:d@P85& +19APt=UO{֙WUMc%B":\d%0-lj\魼Ee~t- aa:[=Si3g~N Fhi -`VApѩaל;Av:0@~VS}h! rN%{(x5;Z?v9a2;OL+ɸ(^ 6ϣL>xƐ8^Af&&,>:W ̑-X0t`By0>H' s<`Q+b}E>/ .;oە޽8\p!5z+T hl{ZGEB>c3dRs4&\w !$]Ͳ'MD1ue uƀ NnW'c!8}!;m+ebp?~:r&d88N}!UG _.Lơt45($X`CN(Vf9nS$w\G7F+Vͤ(X6 O_Cj|n R"bv9co'@ EA+3fs- Xvcn xwaE?NOZL c(̆;jr +*eov{{hUM;xf[uQBi lNI? ]Ec'lST3_ +ٕؗ%C6" 17˰]>kp!d_31+w $ NE~|Ntuy6*2'xB,nPG$?90KorjZV+7X ՈHR }n6U?xa^iX"?s.."HY\,B aYe$9jrgŢLf x\"Ta\4bP7p[e\Bj1~ӕ5+*,C(8xF'Q}x9fZinmZRڑnX\IPgE KH0~qlӊ^@AH:pys`޳ġ]Vf0uzIlDW*1r;id L71; dGA"> y+D(O%S ͎[[LZ{8dnt_CL$Y xciJ#0n _mztGg} @b\ݴIޖ'փ!vl?4$Tt>tvf 3A WV #7&Wn ؘL42*8ܪ#hp8]u Z\?f1?τƽ*i<Rͼ?sI&Y3JF٤U{qFB,EB<#1"(׿w&"?ah5[bFԛF6?BGlV" j]Obg61i,8Lęx,;$äb(zdUv] 4c-;eΛ r!.z&]]*IϧjvŽm3/&.F,w`  0q'\́B_;%moI[+ᇽ12%c,\5%ȔYڋE Kv#嶘y|(кnVʹoT!W6MA1 ]_"=pv} x3 w8PEğoR0o*n0z3-PӳpBm~;n$0(;p@R*@/Mgɨw=NiQrgTW)cxPPm> stream x]ے}߯SB,検*'v$rIKiW.M٢33}s+\[[@`0>}gbdb7oEeYunˋ:Y׋˗iKI]*M,...^sU'yUIbyz.e^*zJt.߮RE͖I'M6J]-VYeJzJˤy/PzɃ:-6:󬪫>ѕR/g2-7Adͣ/TJ ^7zB#CvVEVI5rL[ֽPtjj%{KN~2ǯ}~z"3e{QmrnF+Ji&-&ݸXeu;zONV{cxSawF#wT &<+'Q4W Pӣ͆S!*o;+p@is5U )2 Cڙ̓+-WzQꤨC?]N&D)wAoa%ȱﮃZCʈphAwCK`Ƶ7 hfT6h ےa4:YXg(ݷcy`8%Fa2qMuX5 wl2d u!IՔKYa {Z0~'$U;EN~ 4 oi’6ɀsA{A ~sd |Cd|ƶW@"DRB%XXM+k`tcT޲ѨAi Sjڿ"L!(E^?|8ޚxQٟpCԓ^p HMl\KlPc?1!@ U;d UR@(Bt Već:5l}F{I-ʷI[,V/زæQ*ڶ^϶!k.+~E^pD+ʃrf;;sB[ryOs;08gGmkD1d8-Pf&ًG_sCsyCqڔ@@H4E>I1@َ6_'C[ݬnBso\ԼTsvj}*6F PmHH#K!= 1h,m\Ÿb 9'DT ZΜf|a8Ny`:*jJ+t0jRjxf7%mZfCchQn6`$?0-*؟[t@$ܤC:wz(Fsx T@HzdwiN|YP+=(Vv!Ģw7' 0G'vM \S\~P7ӥ2 j 8E3*M u%4(SYCPhFzŘTX@ Mn>c88wm:~h2 7p⦽3n=e-Nb%EIsuucvI!{:;=fgwXhU߀ t4wc%o45 BKOKץЂ0brMą~`b.ZXIR-j)|lM6wpPkQA^0=[TӂdC dKNb}`ӗ,%}&22Sw=6ܡo,A$M B.,E*)D.:`(K*.*4с2с^t`.uq_7GE$C@0Z; Ð' ǀ4]E%< } Q D)$(  r^"ebTBs"LһW9 g"zǣJIFԕ9钿fG"yp1/y/C0=\CF>henpe>"}c1 z?̌?0u ;Z̙ULe>rcbfft.!6lN5 Io`t&{!G5a" MkY  G*A]7WtW(-y[m6%Y!Iʚ@5=cG L|}(9?艳>@Q\As%oUA-h>1H];fSB#ݎVQ ausJ_'9/h2b]+HKZaAj󈍦N~)Ba u iVlҬEZ>3N_#6f`Ƈ"*a{E5nR9D%0#.!08c2) q/|&Kh5uCp/d+9x X<.x( 2plpu,';v֡9qD\`)va'wWLxqlo@TI`{ Mꂮ 65k4f'JɎ O%Ae@=RkExg;I{|# =>Q!'cbыFm9hr<c QSa܀?zʶ剣+h5uQS(q}V8Tv6Di?(jʳ$ݮ)1zI)f& }Sۮ4~H.qh&`h㗺ԑㄐύ MiÁҸ}Ν E?F"Ze]2cBtB'O/9k_+aоVy#Yyv}< 834%A 3n h'+>af\ٲZ[AW> stream x\vܶ}WZy0 .;։ܔ5rbg[rHlȱۥjsW$ΊYۓW'fEe:ϗG'}&4jv$=Ig:d=[od>Nn?O|1-ۨhFZ|gu6a$_S8lFlQua{Ə[cPtرi(# j1r\js ^ShpLPYxyfI.3۱TzrU$ sTlUCP̴9 翉PjhLS0$e?yz>lACZeZ7dʤ"p4XV; SnMّPr8"2C &j,h n:S[ᛨIn08=ǯ(48v5Q=Wj+TA}$yW CZt5>K/çP-aNVBQ+HR# QY$e'igZ0;#\N﫴xO] QTG0uoPxq’bR_cqj$N,' 5ڂV;gC߷mfNw҈j,9=fUM C$cEQcrSs>mEvػV5_W%Ԁ-]-L" &i;GM]aɜhr2;#axCOe=<<}{Z_ m=t,ߕ5 KRBF&ulbv6]DEٓWS)?TDuJNCVDC1Q%@g{4[%-d2qK>OTEH_o0lgvZ&Ow?1m(ҭ h$6#.8-ä)"+UIF>OY?1 Ul0QM>} fiͭ|A) V S]Xh7?D q K4t9Nx`,X/;ˆXhɉDd!LyoEGax6Jѥ q 8L  L r)Lj!S*&FĐyVO{J@!Լᆪ yCZ8)$ٌyQZ_ ޒhln5&ƒs_7n^Mn_Ta5>0{qڂQc[PGYt2L><~>6YVh_wMDlS:Wt)Gy>KKZ -QNh~fʓ3DΈ\^B1i(8~d3@h7U0PIE˱=Ə"(oQo x&Ɏ/Xߧa,Um)bDIʍj:1(K;7z/"Ru \T_MH$LD r hZUqY{ݿ^1ZF|)Jm1Qh*tXxPr#KBvY浔}%$jV4ZROGQ#2CEns%DF:Ba_V"Pk{Mk5c|ŏ'*UBS1! CMP!wI{4RH&y,硃Bbi^Xwb \ +1 CcYCYZ~!4(6Luuw'+>yVgL)x黻׋Y*<~rLċmi:oL;eM[o@k&fo̓M|n؈zȭIGi~@@f Gd1}%?oV¡Ev{wa#]c3gX$ 7 *ySgq^ #1XCNaU2gyCdu:g+Z RK/jH2TEj&*:0@Ez,~TdT;) ^r] T-LX &-V?8k2Qިf kr6 Xg^!!}P0MG`)Y_^KGINdו=84)_w1ܧf tj^0gC2qN%77+lZ tI_nB6endstream endobj 31 0 obj 4020 endobj 34 0 obj <> stream x\]۶}_?TX4IK~H[u6imt2xƖc(HpD8$Y~iY/Z~~4IԳt'Yu:4rv>2NE=z2J8z>$k:ZTq_'ۨZfmǼuJW%:ц"W+^z'4ݙ9hpqD*Le檞1M0a*oFP27H?y`YpcWq.SӕQs' %y*N6$P?^djYPsxJ{*q"RE7kZÜpYY  ,RX,tEWee$a9 -GpdF|.?Q@:V3ayŎ,x(+dO:*OtF@G3Gr3Л' ~ ؔBډ2rW&ӢoM|~m;-R[FGǪ_XurJ FQ~K,5e%iVa&99$ie䆚C0fT=bx5.fGv IU^ѰsR4AKQ=cDC+zFg|֣[}8R^3, 6; MPanh~SN?w@߭g(j}Si c_Ý x3ϪY3d@E5c)="UW%1z+mX9!bAn4lcdv\quY缥D^BpN:SO{ BZʲZb/;SF,`tW29s`"džZ[=f2X0Y[1RR79Օr01E)Ɏl0cu`R) -:sMf\ƺGxG4cj pTHm'`n'>adhWzzĠŁAK OZ tӘc Wy% ;«R[,>MP-)[ndnS6?V8G݅gO$;,iS:-h|fLê)w4/eJYQl^8n6 hxJO~CF4upDKA"ܣƧfXpfd5ͩo9/:''{=Nޘ@`ͣ&5Fă ;WdKS ԋiZQ_SlmCpҐN=<*.'6 ˘_ʋ`R%QP0,>3@ Tvh*M"MXyp4".> stream x\َ}@NA8v<Ӂc5ݞZ3tlF8{JuU4\jK"b?v{Ӫ%]|~}4YI4WNhq$Eq۫"<dz2Z\onhyi|/'7ݰݳt*w?;ޅw8)UOϞ54.<[~Vi;o_5MV:)7QMR˗Qi^5˿k_ ^S߇_E+,KTq.Zey\޲qJR~ucuUOY}4, ?z%g{/c-L^eɆE|nf-Z?t/ub_"l6(L{R4e].ceO'_e't7l7mcc'IQ3> BN%#jp,&`V(N \?|2(գgFݽX%GY|5R^[itBHR3H)1կ C`_GJ=+oET*%UF~,B*kJ/dx'Q!^XL7̒j%lqb2l|n)e%z<諠2-s 09[^GAb/ H "DX!?G6lKoQ31MS48,Άy Ѱ24ӥnSpTVm{2]<мԠkN 雌VCqifȶpa3YSޠ)K"<&e5 6wqڀ;=MA*w4ҩ`Up-s;phQUTAoBC0G;L}|{(Nq{o BRXG=2n !ma-A;j&1$joY<9(wYixM,H,z%^"KpM$vG$NmA6YpmÈNN~ԯ6uHLix)լDzZTXƑʀQd:^ھ,*u?B*^W3!ٞ%D,qa<4 C 6vOL$*w|'} KI3%bĘr*\Cf_';8vEo$4ƝPAzYz@LмĤzVQnVNPOl|n!g2^8u^‘Gol9{]3bYЫd QmZU?\xm(Nج<䄢iLƼa `{Gf a2j-ke.^iMֳ?' '"3_@N*kY3J U67"?w1E3̢cA%;Uٯct:Wj ^tac{fdh=- ,Q|ӏecj|&i-$MvldAQ6ԁ'ԑ׼-yJ'KfDߝJ Ĕ=}gНITh0`:`oH-kfy[%߽"j&A:9S&#Od"rhBD;)إΤݟɣdn)/I3"D3J36n*64L{QY79dC"Ym#;b衹/bY ǨfpO{%0YԁJvn^]þޝobL@]xUG5ʃI 0.I҄^="ߪ/lY:|-jOX373-'\f>őtwT-q lzʊ6 a&2}fiKn„BYGLHDQ,; =W=+λK3;m"or;;"0t끦KҞ A őjɼG \x Q53;I)iƎj1DҜ2UfSˋ|sB:'u }-'gQS6t>:~Clک-QnӞ;rDњ8eN "B(Yi$o gF`^ ŘE <[=gc@0OLZRy l9 vcM97MLMhg7+{N6q2F<12 $d<߼'%@n9C-:j|ƮPD^%(8M'azԡIm8MeOyoHJc[ppa_ϥ)ͣo3 ,Y F)*Uaj(~;uLM&x~־u*FM%s]|h7)\O^QM6yl\{c*{?E&q3"C/gc λtztsg# L)ѐ"~$͌!I)_> 0I%\,U(Jz[/Tk_> stream x\r}Wj^*oY$qlqRIY|yaR4?:2'Z)8$4m RI\,afަջܤ+XS,kv9g*a})v(4Rr>UaVՐ{$`l {b`NE!lQ+D)s2ϰAIR<en= KO,k$}PMhL Iu=ly}Fv z#h{uQJ%ڽ}d Z(kCM ).ؾQC+\{&⑅-Fںa%b63&ayhe4:v*HkKG1"VZ~ RS޴]^^9 gwSsȥvy+``XdxI[kcP adc4#ᾸnLfTm E'|0# % E>VD倾4坷+&Ln޲;*IHy,տk_enFwL.#mz;n:: k%saTE]+u&-H-ӷ p2EKԽk}5ݮXe;Q1^hǽRoqz_Vi" ' s/6̠: __~G.P;up6/ΌƓ~Pgxh[P~@["榻F_vV1mĻhjXJ I Ѵ,fCءJ;'J3-ߊO"^h}F@.~-[ٰT,kwSͣp=ݺVn_$JpHщn|lZam@uD"4\o![vyyZx$^N.ńGq@Yy\XtQd! 2Ow¼0*츨s^6JF(y'Fj Tw(崑@jՋ"[hT>ᕏnjfAEa)\EGIU~*'GT'0.|Չ NPp3j:d:fND o8QD;mtOGb#5gV~<2!y&ԋ;jafI}EqQ2)!..l=S-J[ľuR>ކ%4yQœ!+r=6;F [9Q?d\m3ZiX`}ҕJ,9 ' ׽dn<겿eXe6 wK/5ٍ/$;0Qk@tRT=S}5T1KC+e;aޟR"EzRkm3Iz-BBԇ&bWfW:F:sfCQ?uQ=҉J@¡cK;3#/>Wh^MJ ١xtlɛpԡO҆'Ҵ~*Ej|NwS<|MJHG`z < g،D 6 ĦXi*d~P"#2@?4K΅p=ZYgyN`|_[A]DӥMYlC9nV RXTθf[}/5Hި8qL]&qYY(PRd'J@d|~',3,Ύf 9R.'Y |z;!9OLapY͎#Z>$LSUL֞N Ym裕E#[)+ffaIEE RAPn@me|Z0$r8z:% ɇ1L*KxBT3~K,\:Osh݌QAg-Q(]&d4gt=E՘دDh 2HZn?J穚E-G>)Ya6{bh,zbaˬ.,_[|JNwHmAG|tXPO癩i#>,{DYT1y1a(l8#xt2GY)>&*f=١~pfŔ䑅2'TѮ*\#,nڮY(5ҲfzL].ʯ?[Z98V"mT=;\fR;yuIj@ hK!|#='XL>8CpU>Fa^5xf81s~Z{J> stream x]r}WjB$&+-Nm6q\ś-Z"ŵz#|o3݃93=S `}>=w$ΊYٻY:įg9Mfi',=IgiVuΪ4|5;ߞg9=h٢yZ7g"Jz~ey\Tj6ZTqz~GzQ'ElQeghѼNVK6f~,Ajw͏ ,gO^(]cuD/ҳ(Uu&9S4wvtOοl9QV7ӈp,^SϣbR`itŞ GÌ04FT_v|)Q]a^'UeN"wїU%R2VUT2]hUр1+AuY{ ュJٱ;\W/tCľ|J^/O4"+;.j<#ˏc^t#䑥.zr y4hd(s c"+m1L?Bm;C' ` $pP eRȜiX 8[{$54hibs4#N"Ϸz”gE`3(Cu{W㶈Pivc7[.c5g͢w-;I%uF(0da~Xj=w(._=\jH wPRv S!üU ؎/cCpsM9hMEPyH<г3*85T]\ItPaP{ys9.{}: S= 򆿍ܠ̹UeăqM Þ{co噴qc76BqF2HRL` !Bde+w2۾C^h۳f,LSu]hHlrCGn\1àX)9Af%jql{_gRj HR{/,%q-]Zz482J#J^<_p!E8KҋI{ߐF90>7y!?zhaԼj*!B-N@*,_G0ʩ(U4c$S+q|gm$ Xf͔O7l&9q@x4)ҕ = N'FVq'{ɞq1Nf83N=d' dNdS?dG~ L &OEi0F=:30;.Nu:a?eF/)IO_}镦NNoF.L)1jICawLQFXοKmC5  RI%\|C䶱*a䀷 B)vBc+r *T;O=Q8o^_*(!cyKB l܈lFe;hz>`Ve-FQ QpbLrv25H\U_Atp:bt< BbQ ɽT"YS# קp'~A'M r?pPU$2#}Mc5_d7XZUv{$J83I.( sph_4oh[- EpLD]/.)~*{Iv1|icRh]XaiZ;a{d"`D#̯r! Oy'?`)"8& l9v$;+~v85[|BL Fl}8 T:~, /tfk&>L wfaaWdmDy@.Q  O#::iNt0td7hֱ7d'-R[(lbA:lti_#M)5x6ʨV(e翹j~] /z"j&iZ'IYT=8m۱Cǎ E8X cpf';6grpxT1⠅ zY qН9x>;%%82u^Tpn8MGHG8jcSG`K@r: К~@$a2F]ʺ9Gq-5N>pE6vm\'W~K,O, GOD̬ύ#8wb;]eB+n T=dw&5A/)}jmYƴR n+q?}%:Gw@CrkiQ}&߄l?H N<~t/S%E: 3lt8$ | )"c,b:[e)YM,S1* !ʳ8mVG 545m)FxI?[ev""3>ǦE]j~Q|k*@2!F Pǐz'my(#RC'䊋~@.D~ƿ`R1 fe{3bykJ`x1e[ca 0pUV1h> stream xW[o0~F<;H{`hHC b&ҎĿnb匌>sܾs:\L_\Lh.˲-.LL .\6Ii=̬\*,Fk(7920/X| Wt^¤x[V(Q:Mܰr+uLiD5Ɨ+:uƂA'agp@vl,+/ Io='%/(:`ԾD2)5V5Ԛ(ԯ{7 c+V3@!;.$Lj_D[&uX# GDMw85 s=N"/PFHy҃M˷ɝK_X^ʪ?(O]CjJQ4yJSܸ_*p&R>aId4iC耄x{_ڲgؒs4յɝn&lzO mdIZnH050',ڶE"U/57Lqw!}~V/X0AYg"?Cnxwڄ()ߡefgY6vDhÒj P1:8,@c'P jاgMz ' 4:1<ߥ#3)GYGDG@ CuHhd-ՋVi *c4In~nendstream endobj 51 0 obj 922 endobj 54 0 obj <> stream xXKs6 WV13~1id;9xzp֯㬓6 )Њ:x<AAhegXo͇VQnQ9zee]]4< M㭅}6]KV54m9բ]5'+ttGzF+P%ϔ֤Y%pL$N[A)Ew^֣oU~n~ ~~NЩ8.̭t+5BRǼ T9ieMwCF -\)?o>#h!E>Iqu1Yqwyȇ} A[W\fͻ a=sn:}٩#PĊ]qm_0xgU>tH]>'S!+B~8fgp,j-aDX, Ub1ʏSPm__e뺡oѼGG!oS NI2[;ΏPdjZ:kmnW!6'-85eGĤ6. sI)SGN.B1ΓVה Zeԧ^!aB %RgQM>R(K |N;e "!r:j }AE*]CCJjr(ӫ a}.xL5^i4o0*{|O4^hїZ0f;͚Xx?B~H/96/)='V *񎷕epζ:Þ ^k}>kY:C(A|%-EwBV7BuI˚t +S#|atp VB{#el<Ԣ|%m4OJhpc{|ub">~L.CaJHYƔ0CR+=yM(VB(d]A^9_jUiT6Gܠ/ߥ_=L](:VkY|WZ X5 L*vxc*/s}pOa?ۆ fX{ 6͛ IlЀ66j85*g` 3Y ;;,0f/ *2jlOI\wwEB|zh2<*<@u uE9,bA¡7RAN"mSeqݘeyH5h4"FٔM&& |F41ܕ<'96+w7KgM uPYӭ<uecsy^0k(^&aNOܬuW ý1#ƌ0QbuОX&V2zcɰ R`A0D`=0eL"rW/xG!m*5A h`tekW61yK0 1Ǫ:"g<(#E.ـH1j*ix/ % MTbʋO |+[$iMUb%=-P leXhm&LNHjh>` 3<87G866{m+endstream endobj 55 0 obj 1517 endobj 62 0 obj <> stream xXKs7 qMmʹiӪӃG$۲ c\AL0r7I? I&L{[a@EoߜaFmfzI[vM VD/[\62eVɌ2 6-OMgc]X5K "k)1vF:)A^iz;k4c:/ۻY-C gywR> W݆K׃j񽓃VwW'Ny`m˰`^AXy7`}DG)#kȢ4:Ln$|6|y_wR `( 2,~s|R,'GA6KIdLgא0ڧ) XUϒڒW 'oywhPq~ە㢏Oq1ʺSX3 PV\\0AVr>6eHu_Ր 4ZYV>x{xaɶSǡa#9-g:߲l*=~16$~$.Cb~HiIdaȠ1y9~ܟ?擖7ӯvY]g޲|hTU`͠+:aH7>:8o핗Jrx5DQd .m@>Z kط60f P|^Ͳ 'l #a;dSmNîlJ7`;jH% 7$ (5cb$O_#|~irv~朼SJ~8Qtߦ;jJ& Ơ8*zF^:{lbl&eSxs~k+ҭJ&+ʓQhZG`Me/5dpҪǀ5Q0+0JWVC*l#`gcao4ЗB0ȧ[+@Npkg!6 6H (cllUlP<a-EORQ$2?g F#*B 21OxN#ӯ3sqg|AI *! ʲ Q6%I2 e|oʷ o_ 4 ]Ä*'&CX\L $7kate cqM(endstream endobj 63 0 obj 1400 endobj 70 0 obj <> stream xWKo0W +sE BHEmtϥ*;xUfw+P/3})LlYm;V4[)Ed~|[EY+sx>[()d(BmVYUZRm-%+AяJFݗ{s\ujrUF6y:⭴B cLluRG&H,pj pn76)HQBZj<1*KfA^xq`^8*tf9VNcV)mD`ӦZ6~lұtuhi27=uMG,h)[e\hkdmqC=EO~fZkQiROvYC-ې09˗$JBxk|uNsndblbԹ 8kcD1<\m DΤfJف:u;0:= 궺ʭA\/~ ̎pj 8x،wqxq'vR.)5Ԗ> stream x[[ܶ etQ$%nSAy0`x/ͬc'!%u9~5p|BCVJ7>\ܭVhڶ{U[eQ.m-M]om쯿^پu]7]w|qڞRɶ+OJr_dmV,()60vnhU{jz m;z}o*YwQUn;-Y_,Z.!MوwfX/#\CnR5mũAhyG8&ߌ=/*%  CUҎmQI#|OaQ~4KGjd8*egԽifgk~ʥB9v$-'n߭> cUjo2+Z=*XpA]̇#=#$?AJLIIl#W4jW3&Kdv}sect$ELɍ#gd:c$9УpT92'f/lUc.BGj%ɐc~D(:DxfG>*N )9iOA)7R^ӑkV藴3~1h!=- fC\>8Qұ8mR2Nĭ8 dޞZsq$E1n!N08A5GATLCđ :q\Vr6fP1F-=/sF'TUA֪n 2a*5f^0S=- .aT,al@jHr&lzp(AXqi3q "ͷS$}>g\7'ėHVۀQ#@/P./CQqMs\&`p6ܐ)MxUP -s `~8κ* iw L#0xdz!;08lbd'Hi*5) 8K%F` !lu R)ļ,b5c W6-(@:a rFF7 3*;TE/ҧa=4`'DTPS&wkWT<:12ŶJȬQNq*7(`47 >V=3!x#9IPuv Ԯ 9?8SuGRd3d͢m,kG-awx"3~@xOy-x OzaV@tdGZQAEq! ;R0*qg%ocp!IEi"ЅsMѥo+Wf%0~IiFg߭.^dJ;ɂȬq ’*/FK6UѺԖY׍n6փhU^N.66fzp8okM̺Qc'<[ Q!WZt9P{TCtޭ,jM?\JgHG^:HwK^t%G4].MkՇ.t'˵=_V7\Y1-oسd{6dh^?7ڙ]u2O7V Wn(GXu#fУinYjNufghKsjI3^^H ,=2?ζa&Zu&] Kgx??CT#l9d-Rw(cFC$C{Ẁ?{=[Fendstream endobj 79 0 obj 2637 endobj 89 0 obj <> stream x\[۶~ׯL*f Aikg;yH/ײc'@@f:J| fi^l3opsyy-RQUUm7wO7?Vdil_nEl6mBlw6i#Lb{]'LJTWU.S5JiT+է͊fOƟ%WY*,E1jRdmWk6x~sNjv?'MuAN) P}LaiY/6*bꘊ\bǦd#Ѧ~K:D+س2@wp_Td+8)MM}&UZiμ6߫EYd!iVۋVwtُwvw8\#jIRkJ!uRūg9REp'^abx(XÕL!aezp"bIO r4b!En|]`kL>Tp52yDu~4yŤdE^-d aT$'v 0_'>` CC xg若20_Kش& JlG.Vh_ JS V C^#:_P_OSMlvT(f#4 Ԡx| ~Hh u/e,*ñ31L)k *A *3 ^FI`B+V":vS]vxUe>e'Gr,菗c玨|@q^7dK} ps.M 7PPl%kP2>!vGsώG-1A5f:(l~1d9?4OJTO#jgRAX `ʹanr8^T VONdV+R % S2\ FDLGSx(;3 9 aD,qLάӱ<\ Is\_-mcuhzϽS^EЄ5=?1vBj;#rh^G*&{vs rӲQ >oByCebH0`ޙzy6T6SK}Q:1VbȒQ`TO0 D[([0PdϹϦvU E` |D,-tvTBUEf8&-l4L?[&;9 X~2UB3_CZj؝d3jaL8a;,}`mXiz3"#`m۝wFR+ $CU Y9АP}bZpE$/H_~~K$xwg( LyXk0J5g=ԞX}wGC ݱK̢3euy={"q6RnAg0j9L0w<òH7Ch\ !6 b~A՟sI.u3m,7zSNC@[kQXV2 u HRQ} F2F1< D)W\  iXuĒD?,F kvnGMa-bDr@b(41фht3v?Ov !/+۔q#  E+pk0RHXӜX~=@}r5chU.fޓ ?x[ YG eg_XY'JҬ |u/a䖼Z.ÀUjtg`5XkcG_Ox)8yI'φ3WРlfG̙bwms*@3i`b7ʔs)`!G㼸*3̠4/ 街Ev Eٳ+JH\4ܢ= IL*PᏊؔo Bēg 6*>@ 'v2q3"|ݏy˝ANratMl?뜒p:'Z]5ۄtj,8 x9q;D2SZ6[Bu )tp;_1zV4Yֿ=V2-w-R?aFl덨F&UJnrvÍ|l&S,x!R-(Go_i/'(yYZiRJ)_PQ=/L -Oíb%J?b8СTDU;궕&~`iUmUI{3I= ݨ] !"E6EϷC˲bohsu>&l!u ,#OmD{h9(Z?)-^ԅi!D& ϥg C%~~dE|IbisJVP}+1D=61ΫFCɳ^TdnxWYL05 %cD>TO 1w]GixLM<6[S=*l-A[(6߫~ZQLfqZo?Z˹/`]XBdVs eY#)]"Q4LF<RU$Y.)*6ʞ٪<ip\oTC6~FYp~XA j2dٷ:YhE=>p_u#%g^nPY, %Vh++BI - a7ՠ1D"iTMA|As*qP@=Hendstream endobj 90 0 obj 4198 endobj 97 0 obj <> stream x]0 DwmI+*PB$[NWiyVco?/8&diO8g1$UvP:TTyt(9z_ٶyOG Lqj~yWC]*W]0Qendstream endobj 98 0 obj 148 endobj 107 0 obj <> stream x]=0 wmbM *1 U_HZQ~>ٞ! #Ɖfa)Dzpt@>HFQKGVu=IQz~XOm-/v_6DAƃXKC?p_EvgUW0nendstream endobj 108 0 obj 149 endobj 117 0 obj <> stream x\n}W Oq/`#E`VFHc&{NO9 `5d7RuT5^%qVO_\m~>yUiUU'ڮpqū4YI4p']5m4I4vu=aMtyi[E6)cVqҖ&:oXoU|o#(nZE֔Ӭnjs?ꤧ輎4(dHWQQUڦk^/"&MWw8y"S}ʓΔB7+{5qRmɕgFW?.=z)^l.^H`oqiZwQ`4M7YZi8n+>:(O㦬Kndt -r(gmڠNX~PPW=,RZRi^kuQD@̒HuˤN_@ '@m<-һQH`Sc $5OKz-]:G3K50n()<6JJ %tEtz-2d)O3NƷ7'e|JsX)T2bBBP_QT`dA(D.Y&L6!Y|PL#W5hԛE6WyB3f7*@`P~׫xIјj<:4Ws[H.ȴw\ l m5M\QN;f=b9_H Z 湂g:Jupn0C2(9t&ˬQ0fAX>Fp~[eF6J](2y;r?rX8D8na l]'ێޖ[0mlzy`M6q3qZW&*_ъQ_[gGGPhBZwK;`HJcɓwޢ m( hD"&.|La>z_g[yҋ+j#(x86s s$#-hIDGIsgi{ / 3 ߍ &DC쁅d%WD}?#6Nɦn T}׀4s̕l_{<~, %xnzz]_-\\Y*\Ė:!˒>< YY|}ZY7Lj0yocvo!oLeYt `!4& C[o2fcqURYٗBX~x~mscco>6&UItTNQZC<-QC+!x3M!6IP ;ЌVhdDea(-`zG{CfnA=$2%Y|enqJ3&)U|Aoٔ;J &.Ϧ_PG<9  bOD$H>gm~L3 o=Β#f .԰pqNUF,:$lQe sИq 3HjmG0J27TL4o 6xceyXZ+1m N8SJH49"ް;X`aIDJ<T)iCIOC u!㎎«OW{҄^EZ_v)ȓw _B%Ŝsyĸya֌`tBrR#"%$- 8D)!j>yTT5{^Jyך_e]$X'&`/af? vjuԉcS PRM0yÜ8Eԩi+e~g 6 )y17 kڱwe;ˣ"=knƔkD͙x f3{π E3!>z;Zfȉ/|0R X_@4f}6hV0I*W;xzɈ˾1XwvqI?͡痆뢉Nۏ43 nuɓ҇ qJKoHDdNOހwztf<c~~U_owMsƑf6i^(ȓ>H`D'쌑xv{ #t5ghlJJLu8⥹2E`Z M :&=Cc.Y"b>0c/)J{q8l4=m'/o,5[HqC j>y[ōyhaGsBdOL v哐JmvGtN]Mdp|w-y&RAEG(Fye[Lx;}u΅H)F6=kbi^FDi6~.WȒY4 ki$L3z~HPL'X?$}|%'!*H)jAװ.F Oj2qxΏ-(#L/ =jJ?R6I#pA} %AZEwQ_J#h%$zd#L^/PY=:r>"*ցI V[݄JL2,(K-T"n ѣ͔e@b-$<3V~MH~į79B4(MV:% k^J"g$Ǐ:cl+1x+hiy{B.(  I 7.fIiڪ =7j]]~zO5PлFEB_b FG|hFG᳈vy < URrnMnZeYYm#zm W)*(9څ z)< K& )yiPQ/"Ϭr|0@4jwSLeUxҜAO &tzuY5U*ӘXLڦ[endstream endobj 118 0 obj 3687 endobj 7 0 obj <> /Contents 8 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 61 0 obj <> /Contents 62 0 R >> endobj 69 0 obj <> /Contents 70 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 88 0 obj <> /Contents 89 0 R >> endobj 96 0 obj <> /Contents 97 0 R >> endobj 106 0 obj <> /Contents 107 0 R >> endobj 116 0 obj <> /Contents 117 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 7 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 61 0 R 69 0 R 77 0 R 88 0 R 96 0 R 106 0 R 116 0 R ] /Count 18 /Rotate 0>> endobj 1 0 obj <> endobj 6 0 obj <> endobj 15 0 obj <> endobj 16 0 obj <> endobj 5 0 obj <>stream xkhD endstream endobj 4 0 obj <>stream xc` endstream 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 [/Indexed /DeviceRGB 255 <0000000000800000FF660066800000800080FF00FF9933660066CC0080808080 80FF80809999FFC0C0C000CCFFCCCCFF00FFFFCCFFFFFFFF00FFFFCCFFFFFF00 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000>]endobj 56 0 obj <>stream x흋&'m?I_Β`{B`9P( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP`*uOSN)zW 0 CQm0) C(p n#;)3=x)}{9K(H_7(m @aC(lUبĥ.{Դ8>b =J=G\h/"( MG@3t8@3t2u Uhf(q8͐[= Ţ޲@3$墡0 !a^s >$ep 4Ea>nq:(Y#. 4o,X1|9T;G(ab2}-; G'=bGL^G\hE8yq,rr~7ߠ-p 4/S 8;Gʶ9pCh\?=1&q.Yy G L'm4n8L5K3g蛇j8xbIfXQB$>L ߐ=đc.ϟO84Мज़Xw~9,Q8V~ !mp (GK*gDiHGn"a#"@Q4]cٵ-8žkWP814Wh01bB *J  ȑ MfY81F7n0&$㘋 C:Ƃp)ъGbC/"1dԁ8R%%w98_f[Ux&2Ƿ8l/yiHv @yvB0gx8FpdçH_:YGȯE\ j2wRouc 19S`i8 &3p|.r9T'(3"./8~8>8JXIzф^kqˬt p8^.u۟c::TH%o#*vpˌ _C|Kp44օMG\X8Ocط, 8GZRu1_E$Sm&F XkdxK#YJLfS0l-+o2mwsj!4qeS#;!@;ה1܀ƑwNmxM]hi\\[0ϟ:pdCJ Nv㛩G95H$i1V_Vvݚ@W!Sm[湠d ˇ#=zpDLqƑñZMZˀ_ U\+3?4XϭԶiFW@0=ZNr _DVe`DÎZ)˳)/pE8Nam?`N/pdLGΉmK ;.k 3bH{m8v}[pͲ8Ʊ@rƻJRH.K5͎UƑ#bĀ6cIP95s8^/HuH=q4LVbRCQhH2# c3ՉcjHϲ`kXB@-&zf䣙VQym2) r`~#ԃGr+E~_⍁ۊtX;EF8k}CfǣqI0ds/7+-Z9Th?pf/ HZrLG T̕6x"K8"I'qa&Jz+Bp<c. 98i\$zv Bagj:`.@XrqRpyp53 `*hUB0ˇȶvQD[5q,Z x"#ء#qL$u,UUFlK8-9rNC88f$1Ux+ T(D/)թ8iñDR)]dUؔ*Ў <O{Nq#ݠBqY4+ BT+qNc$Mpd,GҞ_BXK;BۈL82(!|81i':(CWwl &:99-:fn^ GsIگ#.6RqT}խK"Ci2tp>?]5zn8f:[R,2V3lqmQਸ਼ J/1X1}mnñn,}8@R #GsZ-W5`l?va^5G 8WLRsYGk_Ոci2~øv!h q;kc}8JU48XJrpCl8](0c HGSp#J׶LG6X6>']K⸵{ :b} qr]$&[8nJmvZ}64-dG7 j98JD}"B14bbjC`6W(lTst2,ima<r$ ҖMOrf?YM$N 9p y?4h*,UU7=&s85⸓x +wPh #4YWS±lcp3C˭̡Arc"g9 wҦ2p<`@)U5mPqZ: G8 3}U\ishqkS'G8J5ȅQU)?'6[ؕ)W^pL9yO:ڂpW:5cஶXOq.iZ]^D4~x]m2! )qy3ɡYqpYLGȏ}a86.Oc!0wiBZ#@ H4֣ xqQx&Xo|S9q4J80R ~_tlp$;Ƃ #i.Hn;y)%u<=*SW8j^yӸ E?G)&@\_Grʌ#I2+m0\ d} y7q_U B#/Gl}}аoۓT@ )VlCUqbP. 1Q.ƱJHpkWl11Ʊ)%Xހ AuIQ8ީ8hz7;\Q! }?izb̀ꯂWP91c{Ks\,=7wfk:WW9pp Gڿ(plpܖ?h.\oQƱXf`5C=MS8j`m֩Lr'Ʋ?poT}G hǐq1 "&qv#ncH_"P׵ǝI8*8RZPv"0n sz⭵'l= 0ecCc[OaY1qYT=rnMg^CpXU2J% qx!_ՀcvRabJf=6mb?n2"4GŚbpg8Ek3%C Glt9@0^89:mb7ШTF|L[G G<މ O?6K+ nig∛oktqimX8:*Ż_i}8286'Yy,֯s im;=p⮾jSi/acOZp.y8~:j eQZUta⫢bX#g1qK.$F !2))'@ǼfȱRN8.+.(M%Gp\p^ GiDyh\r4G/D}rMpj7x;Ň#2$qL?{GFqqIyqbp8.|=,c-T{y+ԉd%0o嫚!Hqh6,}8j?^G"T$qhqLc;TNBɆd&GxQ1?ut~)w{qD4k(8⫒N *.G\?XDqD3m:GjVPVXhvy?@GovOqf%e/U:>?go9zv {qiL'vq66eQBb@ +1TJQ4#%S%[eFwB pQ708) u iʶ= G>QyӁ: .Xb8^x|<ߛ#Ic (JHoWuK!dGԃcfDZeFj-^ڐ|б(7윏 gi(6p<[]8vǑуcI`SCq6rXA<,d|)8ĂG8Gi {d28N ǭhCƎLX&!hB́cf}r@_սs4r#qmVkJU6pskq|UR]5ʛC8?TcUxckq/b}X_~" }\RygWmKCY_>}CN.m3ǭ@c6Iи;Ώ=O=?zeAْ~D15b-p1vJHkPrb'yP?s+N<с uD83Ť:oƱjtWiJPTzcu9 >`= A$@1GYVeTki3ۧql~'xK GxWW SOsQ+(QDU`sx]eÔXn~Q:#0qDVU3grG 0:q41/.k5h\GeCM0ZⱮL);y$(c7ıB@rA ]fPܲk+S39nı]*K/tq4w<^6V,+@& jEJ]Lr Xeph#-rTeő86`8Gd q[Ue$Eȯ9z񸢄#IP%d3=2PG6S2g8>%%+(;Cǽ' G ?DىcyX)xh[pbG8N;@*gN8(N&,yu`ݎcZ=p$ȏGsVq8:qLCGbň/tzp0,pm:82Q1pLM8&, ]xmqfGtLRG` 4}o&☾T6TpY ݺ/U 37YyWspThǵsc бlkL1'g,8^q2sb29=L^::qdT<>18U~? q́V"UNgr,v ?ErQe8b(uRAoc[icK8z/[igv8679 XHg}GAb#ENs^؉c"y#mY7|[kKQи:|rLU.68s t44F/w~q͢#By8FL Қcq$gڟ8P2XxeO dvj[Q^Dg5W )p8~ l^, սT+gDT]6JA(EO e4qv&'K<]UGs3qܿ#+V4ѤOq͹r3_±qpDYxϞƑeq*(Or6{(Y4t͏jǢ)Z^J<* Tbi>^+e8K˱Бv<Fl 4|UD(mLά5Zԍ#΀Jzʥ[@wkcűG\ŕGq& 0B2#VN⸵, 42BGaOqlv@i֏Mhc8z^8G#tR@8agJ/tX@:~q,48R{^i~b ='F&r*SĸSBGBdW'}\A)yWWjOq:zx0v8}Uk$'hۗ0ŕKq:m8VKֿ2(3] =Ug؟ʱ;L<)ԶJ)ۅ#uXQy 6=زc:q_SCGF9il)]pu.׏?HʄsusqT0p8!tpl">e,XyXDqfdpdIp?h+?1ug+{wy* pDؽTG#_cypڋHeP"%8\&!b,W]cT KѿKF88G&qlHF%#kq"0ץxiQbq/.c30xVeTD $"VĽ3u&Հ#"b8L8r-Gr.GkHLfu98< <Бز[mF/GƵm}UsbSS*9Y`w]8"#笮-^8ܡ8ΏZ,EzPD\CFO9zs 78~$x [6IJoXʗƶC$$N(m/< @|Ő׵8nrrc{Q'ccvq:$]I9˹4A3jBXGXZ]0MԯhJ? "\+!Q-?8sLȟS $*^mk a?j$/ǑQRc":x 9'7r+@3ُF>IQ~ ?8n00z8#}q8`D-y_id)K_6ϔ!ɎR#yEz*wi5'c"qƪ|Apl{sZ\F^Ԛb`::6 MGϋ .~#Y1u1M eDZr_ԫ ,.xv:wCq$,?qS7=^ipL8qlBsɿ gBy&5TOy$ G+$&,av|ۅE/vQ|p0L8Qx^݀8~u2uXyG* 8w[zq>̡VR);39qMGq& vLUXA#UuHYRYtˌnJIH58bX_mgC`)pl&y,bF 'KeqIUW'mkV:[KogcDG|8ij&Xo.T Gur`BއQqQ8]2K^Ʊ/\(ԁ㶂DR0Gp,r9- %%RIqC8BGiV2 6;B 8L8V@fSԪ1աrGjl8oWSTH8_L2EdqL`T(4㾂GrWՒGc8p4 6a_6PGWecmZ4Li (d0熎* Ĝ}t A؃:Oyԙfܱ%J$jUU* I 8#qNRRE珓Y$qlc;mgqEƺQ[wW Q!c'Ȇc1_\ Ͻ׾Y]8p85֏*^ٶ5uzh<G+H8B5Ne:06}XE+]O= }WFg~U8/ ({11uA;GPM 1lpڱekm *ڻFpٜ١IH oAE-p~~.jG4:d6)Ӈc d 熎3>q,K^ɐIq㫫PxcY W\Io=#>pgn#= c8 M-LBٙɱlXn~8qlFq:Kjl[? 8@qT l±酎_G[ ciu~G<\YvV+(LJ58e16 I8V 8"އ1Njv3∇I;ep\@#c~:;. "uӇ#Ty6YRe1gbφ3/0 -5f!X|s :uӁ# GӭjD ;𥜶±glD/H ԍGߋB|i/pt17|U+[,iS_Z82oG .1pds t8V8E %#Ho#q,7E o&p5WHƑB̵ %$y~F썊4)pDV*βbQMtHuhl@dvh±0H8 -8MP+#p؞)!q[~1}ptq<#nD l;ebiTqu]ős"bP8L,3(E>#`'¶TQR+?|)thh=Gg߰872Yhq+G/lx Uaqʨ_[q$H#D=߸!dkVM_#h1^~ZkD7ЩfToX& Oo_#ޗ8o.> lTg$;.|pG6Ч>gu͎ {_d `2 ðjo+4t:#1<^cr7FoDe>3e8O^#q[%]jwHl8ocui U7Eeq$/{vFp"K|>*b:sw_~yupr01vL(xXAǪ6б G*,VqlS8p۾ʁcBj cfd*.qDZze |8rk8>#8Bτ#՞ǭ~[4=qwx*s"|szπk:3 ߡыcUp<|g^>>iIRK|X±|߄# ]Ď//4m8 8Ni(U* ı~_#Syq>_G4 #S(ΒSql2|LHNqܒ7(/(p|i~18x *l 5TVc;Ɓ#9G29;ݘ$wEmG8V5)(CGum^ב 8#Um.'pPOc84܍GCpG[ő%#X?Ѩ_x'8 ㈧ ^Rfqg }' F0wV#$8V0 fgǔBrGf8t)v۶ 亂X͈qٌc=PRp򥵒C3xxʟQz#y /T*]_ه6k)@Čc7h4 jГl#lQhNjqTx#W}+a[kqƵ^ilB|PBƱ ~8^O 08 GdI7G#PR0cqFگ%xo8T%x /L5~ [\GNJRIWw8'SUP!U؎'6n7BJ(D _Goε}8O#uQ35mEOo8<3+FcZ$C쟚2֙pf闇)寮2?xՕ8>aL(گ vި.V0,cͣF4gKdP8kN(x{z^tl8~\83^vW|U|5 8Pa"gвgG[='"ò;n#ÛM@SĂ ۏ#K߈#iX*< ]xe}>mrhбFM8x((c 3Хy8RIo?jF ^ǭG28VXՅHL\&@ıΥr1#5kGfDh Ѹǟ%Տ٩m։vnřpRHG\ p,cǗ|G5S4WÑZ̄cNjMj\9Qػp!8lc.?suv+Gv(y=83-5t?~dɝȥ8:dQ)pi$#JmQuhC1KCq󺑫zV(vԺu.t%ǟU<Œo-R̉,(4#0K|8mbï_PC: GϨ\Wv8FF2WG)p$&a^bF'q*g;pqdGDc4 F[{%w *p*.OXǻGm.#jQFFkG7jҴe5X_֨zu wѕ8a_2QmI0BZGj "c;0] E?%SKXG؞>y L8 G2h*8ٯo[|2xNT8q$x&ِdө=4mG Ω=M)Hc8j {4pө@8d̩_8})S;8zs)!ٳ_!_՘`R D$ &CqYڇ(~)AˣG&HSgetҪ"#N[˵G7Uh<_+KدǟYͥ82T9*\9Ǘ;qpZ#&mr,:18!Sm9Z훌#m cqz-iY(Gyb*o$˶_ (VPW i_ Y#hS%oǿ:@x6i; Nβ5 ?``Dq㘜T'<^.qIcQfY8hTőш#'o Ḳ u 'pi5 PVڄVw*p敩?Nh~r\[qpvzj:7M%# U5JO?ykX4<86T2bqSy83~>i.HgƖ8TԋSƚ#ifQ!=#GI4=|/pپ11u+T?))!|-͵CUu]iھќ[51עM5D<+Pz2_h_8<8BTMDxg{գ~̯ohF }x?Ozz D*:A&SsҦB8n?qLHAT}1l= 0cm25X]Siq{A3UBhpuʱ %YD8BO:DmWu4J8FM8ԪxCXS∶|5Sݺڎ@W/98[T < 21M7S^+RgxtZTGe:D+,R8p&.yB!P^*i`~\v8B.,W>ml]VJ?c_K<8E'W,RSQeL;l7 GOq%7=MDGyU';SC[08^q}N%Ѹq jyb#;SLJ{ 1z-%$_H ܘK:kCHLLu[ 7&Nj\sp*iET6~nj dž\O9B7]NSnCm.@?"R۾Uׅ#Gmb0gFaXǫu)MF0~%31iLF0qd61|LGJg(zMO}3hь#3xñi fk&(Wڎt5#[14OD~  HbC j6> #'2&ǫ5( :cqdߖ4qp& ?5CpTu[Q8FV>\j@@#c*P}gQP1{#+oFIm 7 ͓řϝqơG'G=/C9 , AٓH᦭ȿ-fV[&oC/猋dk#ܲf4j ˇ6(Tf@ipӫV9Եr☚oح.s4UpTis]6'w3,8>uN# 5*7q6߶hȌ#3Ɓ7Qﵠp,k1t j^GiH%`7#IdПLJZ{K)EGlSX2*㈪n#hG 81C8^#dち .I뷯üPp6lS8VL< ʹ-krEaԃG ߀l<Ƕـ2&xQ#\^3C-mEKZR%sĈ߀z$;9GŞ8K^ Ӟ%CBkXc,IG" HW8&δ4Z۷IW~kD`5H*E""y@/j8Dq"*cD Zl\MT[fDu_-N38^.z@ʀ6/G{Z&ZR8fC[&=LaM#26 qOO,iFLט,^jiͥVmm5E'RiӠxo=Ԩ(Ҧ>º\MsE5R-n&sSF[GxCj@4m-nGQSLF._*P  8P> =M֥= (EAX[upդgJRZU >N7տ}6O3PjDpk]]!ٟfSz`sK/:g!ǥ)ۧyo׬ ybƃppٕ͑rh_OGiLصGcOD]-o&鶃n@Imj$+RoLyd!v5kSilph]9T5 jx6{f.ҧج+A!e#σioc_sQs͛y}BrvY\M;dWUUp _ҮyY_]ʼnJjz{F߬iMRXFԒcU\L8Ä#_G]@(LʹOSگlzȜ06ƭ$28󾺊#ے(x*M]lqp1bCy[qus&_q.F rH|\buId0)D/:ց֍WN=J{栨T0~DMٷdS7~܁C-:uU59/zJ #j*snks-n?{CZp3Ѻ-aWS}ꏪ/R #{lr/f; “LYTUY=*zk`$[񳚾f®}8~65TԪ~/%ѕPz}K{p9&弦Oxt&e3Rv au݃즏;v-q||=!"Rۭ ]z#pş3a;dV^+UM< ǧ"Y[( > \(ke\n\8^Y웠M~ 7BtN4[b쏊Dc5T:g[פS>8&9ޕaYJ8Y%^H|9\P[_ҩ,8Z8[PO$oф;u1=w+Y6fW\6}E,O#h;`U[ ?ccZԗVc[a4tauWau#k ycd=Jrڡl?n=7>8Ud}Z7}bG:9>n^"l#Kj-SC4+9m[qmxN<ػ@+4%<;L#b}VHھe.wD9B[f$N Mp=ϘbюƲp뛣[~d}i=5_(ۈ/hM i]IGkVl_`~==V莣o2ni\=5jqDk*} ERUzjYg3o{G?7\Ýfקr`*} dG0)@bwyvj{WNiNrVr9 G5TsokK)cܓT#]eE1v SzgvzgLjO#0b1p?[[y,櫆6v]Mtm4 *ʶ}G5mש8!JP̧܁ zN6-i; ҊWjp {TFbښ܆Y!-WU@Ň]]1c:Ȇ'* i3V6HE Cl6./~ka܎-'`h[{{dDyɆ;jۿZHLN(~:d!Љ?]Mh#: f7:m UcLݬUA$gc Tׅ OM43mw} G@GjD]Tܣnc18.KX@ 4"UDYo+'fUbxd7[Uq`ܱGm rqFz|ARWt%Co!04V$slܭ~ N }# 6Uus ӈl$@.t_ЫJ*u]cYYУb_me%cQ9cgD&T9!k eIH*Slts>"ƈgOM [|Wzu)6v'2m42O3ǡ;K*eESk9'j0ꖱ퓆%w޴ M?:qw>Q}2C!fyVض8B>uD`q/C dvj={!n4 kFX5? Mթze7\M;~<1S<4[F6 2 "Tr14rI|P:givf,0H1t(|:ݳ̰a3mNtedTHAAa>9 ͨ3SVrBs嘃)dG$F,Bw 7gvO~nDFH;Bq]q&4B^yS9:e|:ڋFNw+4wrk|:$#210 ]q\D550p:<Gh# I B'lu^i%3][FbB9<>kxSmωwmΒtd;aBn;X>;h/Йg'Y!dO7{ 6p F;8.WVUS<-4@8s_ y$\Y$ k->&8n#H̹*錫TeЋ*) •whs*g$|E,0HGCU;#Q8.< WH#<s-z5?$)u%\mQc!F8lpM1}aڶC šI`48nիVIJ3C*F47!O4$kB:ץl(l2~^mU{Ms3Jh#* x뻸+3bʌ+W+hϬ2!28'}wÅ^Q|̧cb6^F {6 Zt+qfj<Ҥmxp\O8C>/L:VqPh6c*Ş:]1t\ŇR:kMpT8.aYynh\C7)iӮLcV;~Cz3[;|(Ĩǯ3zKfG B9r64zNB0g : @G(ʲIn#zE=@G(:h# =ٞP[=g-z3: CeDU Y*ϭ v9S9Y(tΝB mxq={B+׳1Z C8B|IT(RP}BP(rͨ B* BQ Fc(tŬP>BP(T+C(nx#≎P>':BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( BP( A< endstream endobj 58 0 obj <> endobj 59 0 obj <> endobj 60 0 obj <> endobj 65 0 obj [/Indexed /DeviceRGB 255 <0000000000800000FF660066800000800080FF00FF9933660066CC0080808080 80FF80809999FFC0C0C000CCFFCCCCFF00FFFFCCFFFFFFFF00FFFFCCFFFFFF00 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000>]endobj 64 0 obj <>stream x흉㦲ədɝ-P$m@\ H|L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2Lr:ռմj/cdh2Mh2-#dZF0v,.1A'OJW-oLwG >pٻPj9meρ^`'=QO縔e&y1h':/7M G𒣇f 3r s G+Y?8ǪiZ>Ƙe5u[8"Mdz{a en G5M_FɴA!ygWƣ @S2x>*5HeGǴZLoܥҗ8 m'ڹ tR/?$X1h2-#dZFɴ Gd2L&d2L&d2L&d2L&d2L&d2L&d2L&d2NǮd9|<t";d:M5rt2YK!P`XL#cXX˫d*8Gٌ$)D8] KRnO1&K8Ʀ KDy;GTpF@l:CT,o4\2ӛ{4,Mw;4") Kӂ"Vs98Ҵ2xnn]p)^f,MWL1jK^tӔ8l8"acFU8 K!* 8ԩV^cai*3E\+Z3 {4I$q8&Mtp'dTZ%O"c$ʫpEf,SA{Q wL3`q9dXER$,Cp  ˷&q#q|d?hdCayk 8T8zxN1;: cfsxÅ8湑q EF6u8VjNQ^v=vnXHmֱk H21s#dX@X _蹑qrJ `/1Ȱ\L~a831dT^c(3,oplHٞp 2*o87W"ePe>#1:+H%1k5'ucvHQoaIwLs5 ԏc>ЏƑM )?8RAv а\G=cJxQ *': }sV1Ȑ^+_ Z+ љ>çHwA, NjőwMgX3<1Y Ƌ 78dte a3=%o6z]SW!8#0i0=1侮@Okț3c8"cl#NpQ0pxqtݺq I8ɞ8f}=ԞJȵȤXt>ḺR(]8*,py8Wrm '`BrQ74ptHYlI98߁@.bxMk*Fcl_jw݉cxC{周v6,>G8vuo<G_Qc~ g};\Ex]:qM 8A[]e"Yǚo8C1W3K;#aX7P0 Jo}aGݏicy8f=]c},jE\1h'w;GqLb8^"4r ǿddcֵj, %D4xX${8}Խ+EpCoc5D1pw4Wrt4';p,b8T"MeT0:t GMDE8e+đp\K#8ҩy8)N8!rp\_{`؈؛qr9 Pcq,z'k阇 ǑscT6VHNj8^vN8蛿i:ˁ5OeO9p 46cu4YmxMws>4}s _pk8=sr/y=T#+/4Y8`ǝ„c־Gt7^G2*PDZk3踽 }#usk8^!$#Y%qGu|4L׫tsewJbcֱ8f@{Ni'5E8jպ8spK_3q ©DFp!sq8<Ǭ8j ~ %WPx$dxaǥQw! H;hkc$:Up $\GtE ^PByY;G06^־:x kV0G pG$^JaPmmVC8\q5R۱Wq̻~K/Noc 4 y8i!r Axn8*p.YQr֯p ~-#ҝ# 8>o#<@k5#oM48*1e>{?tmpzS9rG;Śc1:G{ Cр*Of|#byGUR9`Ge[1띬n8&nooתG ȍ;:'tTN] 8*ǭ68^pD<~71Ʒ?$w&:xCq.'&K9`tuجy8fc?wmH/_ȝUicxOتqDz_ǷjԴ8$,xi.c:Lwcv@J舣|;:fx#xC*>zg8}}}w;X\8Ҍϲqq̇O]oGV#g ǿ7uէp"sůVor#>iL8i[[*հ坞wZXS) O+Ls_o~Bxp|6vj8:WJÑz{[G? @y683ŸO2G-SNDY!B/P:yC8#[xg]8@ )L^)؍c:`T# WDTO,rX+.~.q1p *nc:vڋ#xau߮)őVp$RՆu|^pdz:GG=q , hY*jѷƱh;p`:GḆFNgk"%cu^g:GT4א~GW`HBq,## 4)q{: ǬKq]ƑkWb*q, WyทhrpeḄT?UnѕXUMtC4tJq Æqqtdz{~UR8r}c٥xHNZ|pG81~TU4)8:v1i8ֻ,'JB~%F?,Ktd_Qށatk_c2QPRЈV`0q_)cA8>T#GƱ8vG8t8>k#;<'Ü [ת~E)>VqG`] X(฿ݚM.8YȖ-H؄'Xyonp%,.pL6b8/*BE9?1y:R$9(.p}ׅ#ES b:RqlY/qD\%ck{ 83>Ǭ}.+_ǷjT8=WIJ۸1 bbXmp\Z2Z#Gf74{\I9G$ 3egRp\FQ{k 824h8v 8Ǣ( eD \98$,ƣpD 8W؍xT{R BR;::Jqq{@؃ EgJ*> pqlp=Xf/ 8z3WtUR98f׵J])`!vGR ,JÞkRtST(LNWMiWGx8n%esq_Y#È@l;:U⊱TȏИ฽!ʬO|LM}:EypG:qr&G0~A253q-#C/?#3'T[vuȚw$šJK`&^ 9TwƑjy&pf,G6`8tX|NwNPZ  CcⅩ3Gyb=O}?[]TO,u:Y5XQ2Hľ E*]^H*Cuf9?'w1/qLy۲GH#qSK[cp?*tÏ4r Ϊ($9mT&)7CGp;YG^wW~?py{,v*1&> Vɭ#!x/TʹzOHOQ0ƭ`#LBq ^q,p.34+p _Msȧ2|_| \!W8"|PPtaO-8C>-pL8PO>+BEGC_(h e)C&SG1>N埁R#MesBU# (#|du!_; h;p|AHȜL-:HfLQ|8nxuWx>t܏Ec '88Gh8kp G>4:̪#j8qD~߿; %#u,r:Dq7DZq9VfL@jpɶ~VNM6zRqw׬azy:Q<{$4H޴~OP**Q@vн:xbLHx+!]@}8#:1G Kaq|Գ8oʔ QǓL O|uT{ _=ϝWjprW7|sK⨸PM3FM߳ 1k$qx>8CK_bV4AetuX9kV Ax3CVx~X" +y(x$pyHT^8{.Ot/kc|ٕő#7%aJ74 ǭ+VʫWܨ GE?5OG1Vǟp9%'8V5X`841XPӕQ+9{aL+ѿIP⁥b29G:8#h AcKg=c.83ވcYUqXi8G@&qKtdñA $P|zb&\~S#q̐t ,[%@Agt6q4ìcK58mQLhp)fC̽R#8am,Up<+Fw0,ptϧ!qiLc щipRpȳ“i|'#d8>p1sI}.|ǽFrG+I[ZODIˎv cG1]VPsḣ8M.w~Y('O8'(;Q9_ Gx kfP*i@ﻲ+VYIiď9Sk24ɰ6Cx89Tf8|CyXTAv48 P}~&iqvh*4<=_uYҦq/ 溤1y'ϢlC>`X'h8i8^Ӭc?c}=XWȴU86&)q Fx 0<HclRl ~Ətx쒘y{TR L$~#m $Bqr};=W1*}H8~8iQie¯E멢Mb|x#&n^C((,=4Шp?c9;]Ḍip ߞkt'M$GqK.~<8 ߍ#b A"Tccq8oq$n}`:j '9$cI4UԹGYDyM`4(_/EWKnle.(Ou䌖,8c'n)*y\WX]q҆|ݸAG`(9V6;ȑUlp,ښjv41 XIz8![m3k &or4eG `rAzB#fB IYLoydu}0)u3]Д[]l㸽!%D]<ܩI+am sf`ܧ>8IgJsG5G= [ G`Y8exDщ8dc\X~^Pp8ֿDb4OQLqNiAk+v5O:d|Гm8]2WYJP/kX|N [H#rrq$P$E6T3y|4;7%98VuIr<G.Zl3Ƕw 4H[8v}pEc}qYAsKQQu{ 8l d:pbN#_rڔ ȵ.oLR|LXBÁxBz\سNcup1a, p-U, oJ$Ld S&yte\Uh:BCa8̀m ษG}rWXekQ[Dw:w=+chLm±hw6vܦGW?-?\` Fg>qgߊchFC~pozr zﺆT55\FOex1`߅9Dj󃚇82sV9ⓨZ_)س4m7rџkvp8StZ!!R9'<:Mt<r-ʻk bDkp̌8$T<)8-uH`4Rc^@M1ۈ<'c3ubFryhM3jg b@|kc,qʎ }ThG &Gp&Ź{4  ڑk1HNZ{K(6ӆ#lpҏM&Gk.?(q"mx֥%Gp ͠1i;9yO&Ҏ'\Ӈ#XK\n.qItLydo1#5{Q)R-A#H4rN?Bf5B9\uVȩ_E9;p|` 2Ojq/+L\2aC ͚`58cGŪ]M?\xvNqٻ%C*/ *9ck;=&PpL>k? DzptɛSR{%\6%;$k.*W}WN~LxtВz?MoN8qLA:JwXU 8Kvd6,VNsկ#Ni ,J+i8 Oc(ck7`J5WLV}ag㾽x|(ijzp[ X[gR{]w /8fKvNa<>ipevZ8f`% NSv"cO,3c#uGm[*8f q|fa6i}WHiR:c<|ߖxC8vqLGd8.L11h29Y TeScɿ9 dG;p8"㽎'EB,qy~S5E >iX JqWt2ߋcG;\Ɣo(49| Dhٴq.4 $cLin(4cHz(iD *Ekf=#mO22ormD 8My67+\I7BFW G-6¯\4pLooZG-IV{ h`7 N: 'z@ag+Cֈc 8ު"poZbǝG!śQZn} |dwJ|%+`,̤_[}=Bp M*T"8㤎 u8@6(0ҵO^W7:'L~K?& ʂb_zu*lQY ǦWf xes[R3To)Ror9˸5ĭ%d%9 Cb)ڬ+#k;qZ8=)z΀qT>qN|Hc{\P l]촎4qr8{=c&_IWZPH"L&&e1i8 :a{, B+YƑXQRocėX_F',k9Hd{xr aVJ( [1q_ǬH#.`g$0!kr,$$!\AJUI)^8 G|]䉲qv8@s lsrzY~=0,u5UHQ:isY ;_Cwq^^BLhXWW 1޸ V2#@IXLW0Y"j8Ll+U,CMucឧ[68j'YH~a@2UIAe''pBpPoGO\1]dq6g[$I6t\[\VmJiO9;ː4k\%:;TaL|sF^) 居FEė*-9LgCTDmH,?;pL;nM!іX#ŶiJdKB,7J& [$0*k >i#bjObgEHq,B 1t=iŲzi+4{&b% Ԏcg+JwZw*4Y ŎtBڣ@],kĭa}ǎIL%(oC8='zʹh̊~20_5j1b~k3I5#CK{p%:ne@K,<49ȗֹ\EbvM8nEK|dž:f5.q8tN:j6edf[5V| U9\ \)W8^h:uqlUuWXމ?1=SRk# t򻬈KXca.yъ8o%:p< Grcej#CV\NmR$M ǽf#ߐA o'W?KH&CqRFQ]KfK;5d}!Qcx,F&2qiՀ_ njpTbj9[1Gi`pڛ\;̌d6q7KU~tH؄s]_EDx<CEkmŜGOq"Iqt`YǗV :.EƿX- ^0ƽI1]Wy\G WܸpHz$dy w'+Af䖬Mf'Mx]1ߪbđ-ϰ9 TWm$k0JVWM&S$Gdr}Z8]W )~vbՂ rn76#"hۈI}T9f M.SRk Gq\/cawqqcx0P,nU"vmL;Tq&dk@t>7v%?]5U.]͛})dتH KX Ǔ'uxT6cţD#$ l*7]v'#[5OT"z`QX$I9lqT%SN o_>£xs3^2x9*K)(D# d*czަ3U*=L1̖;iW[5\(=1`ZQ>.p<[($NGpB(Kr[vbҧ8 Vr ?nhͣCB&fDa5%⊳712o8 GC#شNM##(Ik KtF|Zb8X-:&kdw"+6?鲵$RaSpTXTUmȫ|g`dc ^uu*ު2XEw pԭ8{7UlXo8#!<UZ:)'[iFqP <GՊw#Ǒ-&[$jbòFrs9j ,Vxnjud8S7Q `K]pܨ@#í__RGo gA4h=d(SK-`ը><.{Ҥ> Dz?qa329 X ->#6R7 EG*X :B+>8 S ܐZ6_|RGo`DU+ۖw‚E?I8~y\G9I j}6 6XnGQN@Ql${8YTj5Ñ H־?)$nL VbnjI=V:Yع ib394 \a1zᩢK"(aYώ$;Q ^.:AW>ezT#GK&Ə"R@ MclqïTOpt,x]'&㖇DA*#rC2ǒ^+9 gŹ av-0ЁGDᒱ䒩j1Yl+XlQ1Qnpt< pT|D)V5MHQElU"WmAvDzCpTY6h;70 Iq8>+"yr(#Gh;iܻ-WQ)qY7zNn7v$ u"cf1mI8- ԓ1ۺ{ʪE@>UL޹Q~`3U~D*]L2cfXR՚Z՘+?a: TTܝu6uGHg>JGy8WC2A,V)nͥev̨HsrS_wH,p#~eSap›)p,Zu*m9;MjHތdSIƵqLկVKe<ȁXsY F!)iBZلcs.ʦVٛ!+ocPq;:e' 7f2*cNI_]1`U298_Z  8>_'FƓ!Dٌk* hf,Ѣe㭢:n?'@B*3*I"i6܄dcQ{h#zC`R??fS_};wчgÑ$i]&{܂#\nDcd{4hq1}qQ̉S7!T 0;Ym8ēiFtb\Mm Tc87,g)c8T)*(uU%5}Ҝ GW0B$G)dv>5`M U+ı)dpt N4Gx)ԩHv]@[7hI{}4+wK[ޱ'A]R8P$swW{`,2TOq2g eb^Qz8Q?*(+v]͗k0ёoXJQŎ)| 7$W&CBrx]y̾Vɬpď\ _$fJt Dj-o[qӳy ;ơvU-Op,qTv8kh~*r?p_"wQ{FT -\߸MbhZ֪摾[ZncdiK6yI>e8|Bn]b8g0Cm)|j ,( Y"E\0yq Tp|2]Q+VҨ'pE |e zF,p|U݈GMk$K虍]憊'VѯE%}bώ?bjcُs%cwXƍ56MoROty̆ۇX%iu|j/wvϛJD1IMRAe{6RF}9Sԙi46 [JZ03fFDQ׉_3ZwPX$~g'jf١K*@U%h!q%س[1dDƠ3|k5l166DJ1T5x~gq o }9$5~ GEP\b{ֻ-u[6Dظ'X~cj Sr$Ii&G &6Q .(}=J'g"R#Qje>?u ب/  3MAW夡&eX-D_$eZF6_ ST%y0*jtH D%2s<<;; b/߹k5U HtHpdv%/uQ1&nژ|Fd8)8>1"Ŭ>9Xz'@Ө3ژ{Fd8Y8>s"lUH=N1pX36f^g(^qH(ogzdʼn 2Ǯh bjK5_U\jpvKEa)"?˷&O4v 3g9كZɹV99Blayte.UqUu9{*[C}xdOQHSrTjDQN*Oa~q/4WWm:F7lL8T U4_'cU YRi8Rε x gLj0kKqpi8aT!buLu#> M GM3Ȥ`XGue'h#u9 ̑5KIőtP_zB_6rqj8ERhE^| ȐQʼnurqj8Es֡vqgl/Wu'|Se+SeS+"{U8aQZvwܐVVBKЗLm˖F9_;?0J< /0 K84|KDDA9WȮ ,'F0uƆ*]}Uurv$(š=gkqb2]S9o;9yxIO~ԹUbYZx)8>Q"ŕXQL*w8"? rV3MDj[nb}f;TN:_P\|$)&6Y}gD_O> T<iWI{S hOm;fLI}~TգGÎK:g; *&;0oeGӥ8[GC .֒q<[.MWD*͒׿3w #!8x {.V&Ʋ벫TkjsZIcz-Ŏ(*(/jv}t48.wl$WYOTpY8Ny1K׻_RǒH圝Y nev iR*uF2Pf8fp[g?$7VphIט㓳Gr)l@{B;%~{TPjP#x, w*HQGY5 GY?r 6~d h6XGOoxPx Tرh"G{&=5Gl/k0Mo{H@6 G[Uozwx䇦h;~L{e/Gx M9= &ԙL^ޠ-AU2ͬR46h:G)yݘLSD\MјL)h2:@Zn&"]6h2҆Lni:L&S-=kɱ(@`2p)An~LwvK\hr&iGỈ4&iH3':L&ӐldZFS':ViP&:,4֑&zj&ӨNz8d5up4Fw> endobj 67 0 obj <> endobj 68 0 obj <> endobj 73 0 obj [/Indexed /DeviceRGB 15 <000000660066993366808080FF80809999FFC0C0C0CCFFFFFFFFCCFFFFFF0000 00000000000000000000000000000000>]endobj 72 0 obj <>stream xݻnܾpyO``?+q/ ҺL) xrfHBI+qxmy~x5 Fpe[6o٨e[6o٨e[6o٨e[6o٨e[6o٨e[66B\-c݅=%Ik־R~x%V}]$V}2hD-fyû}ytNݟ!+ogA>M榱dRozӫޕdI{r|c}~-Ѷ2[4ooB|lg: |{+1U6.S}[ b/'vOR3-RUo7y^諛\Co^i ۿW狓6tۿ GΙ갩~)_M>]}, [o#!F~vQ}F-+@kwlۙUo|1o٨e[6o٨e[6o٨e[6o٨e[6o٨ec߾x?U?τسkBoI=!%n}JZ%?-{*ٸݰʱO߿6uoл׆h=weCmkbʱ?_nX>eʱ;_nXƺUcoPwg_Vbت!kC-P} _7!S}?qCȊ!tTߩ1{\>]}/>FS Bl?Q}0פշWm;ޥd,|e]UvqK_`}@P9q;ߠ`Qann ^z Gܬ3>yt_YzWAL 7G5ͲWwZ\iݖVIqu z=پiv%lwt\9wRv6zW+V}K #@pCW/9;+i "pNoEZ}C魾^.acc @wB\{LTTi ȷm wJvC+Fö_c5<_9Є}C;GJoo?D㭾W8,ׁox@{%}eǷ0W_5WT NY }a!פ/y _C0_{L_na}_oY"ѷ۽/5+K[ķ2LJMI_U5W'/kx G'=/v|ec|[v_Y2=oxV-cOچA|ٯ9)x;3y_۪O؍/Ґ/=:a^[ݛ7ʓ.Ds$_wx;o8JJ%ʓ Gc-?[O}^|H |ٳ^  |.7;yH=sۛo8/}1֬Jʙto}Sپ`mrpߋs|r%o٣vTͻ_ڷe~L_oT- (_zz"yx70&<":I| d/^dB|طiIm;Aܠ/l_xx[|ugp_oAZ??Hͳ h_9L/) Z7XF f6 H#w4"|h_YfyvX`Ek-j1P 0 Of1kH^>/ۯn9?8zl+pݝoOnz[1_qþyӈ߀;Wj諚hr|[qo\m 9zs|mWdmM5RӚs|MaMz=}om#Un=C ֛8_*V^=|XzbKyvgoՇ ȷ˞Ѿ`v_|3\Ra8/7m'|g Nh~Wߞ@+'H_k^*| D|K23m[&:]/apد$/E}|}O9o0} L޼]+"V _27uO?xh ~9e/;?b^ַ%YhW#w-9)HI4r흠oGdVhIˬ,iS󗝟gG 6eoTf>~-<]p_{ ۶?|}Nw ~~%7r#8y@6Dvc7v#V2 Sd Of 8T\ }-GD~3NyJʃl>_Kq)_~ii*~n_m5^^ Ia:2:Å}U 8;qb4D6(O ܾ YvR.@^xy ѝ 6oc_.$8u;9_1_O-r,<-եNK>6}g6׌QϟOb/so(M.ن̳T(g?t.t_|˯O\̷Jf u#}￑Xv~cꝡJt*<~gF/|Go@)ow#B)پv}(KRUU*:!ҵb_?`z=7RkLf۩U*C*gTbVr5 ilAj}_W/q|2_ױoh23Y{sQugוTD/9M [şafE B}AǙ5b3_~y_%_4} /8ˇ酳ٲX7S>b>jL}h_S>'xބ,83 X?InrN%x}#]N |Lqx{t_Sn1?IR9[K6d)kC|"C(LHK8.G|ioc𵝷Q39\X]}{t,H8BbP}o@pD_L o,w6Ox$HX.hXX0r$\L za7?;m؅e 23z1ỽ2rfW5H ~b5\֗{YfdoY0,/Cr ߁ꂟDoRܹΔos`mr;jM}_*-r:-# ; 'zaɫ@WMdzS7v6ӗG W]u> &R^]"O5 no|C`0>~E ڟty0$4_yҾ dE[[XA'pIxN%|U|<*]3<ʯM_P,7jS;VIwg⻩OyoWo"} FVw2-pCK/zB<{\8 ַ|[O74pTۻQW/ȓjh3ƒF Èݱ/ pzHyx\j6)<_!#ko:ػosLSب2H_ՉM]Q}-+˃rvlz~"7H9ށ3a:3Me|D|Jx\y0zAuZ}KՇ%>yqw_z1ˌ#廃]F9}3.aya[pa@䯂꾉a*kOȂ][yŐN'}3@QЙI_rA7|BS&n<Ћvh_wq#椯L 9mYE;qkXH'pd&feQWqE[7{ZӨ㉡X] }/r5bI9a㌫:5PZT`X!:Ҙ0wة>'9/}#ϧ-kES q*:B e^'|ߌG 0VA# t!{Þ7]p+(00v;~*^bAݪrߕ/,7;.%-ovs$#Ş~|g F-wHv;ӃxeG%|/wh;Qۅ>cT\[ 3ӷ߂Q}F-շl[ }{5/+u*awQS/+h5>UnzM }6VkUskR;UuA'w3`6 ݲ8pX<b=_>ӣ[6o٨e[6o٨e[6o٨e[6o٨e[6o٨e[6o٨e[6o٨e[6q endstream endobj 74 0 obj <> endobj 75 0 obj <> endobj 76 0 obj <> endobj 81 0 obj [/Indexed /DeviceRGB 15 <000000000080660066FF00FF9933660066CC808080FF80809999FFC0C0C0CCCC FFCCFFFFFFFF00FFFFCCFFFFFF000000>]endobj 80 0 obj <>stream x흻nKKE=Ӎ=G90Q)"PԡC&Y(c36ut~Ng[Uwuϐ3 }1j>ֽz(-dp2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k''sSDV1 򓈌~T#2kQȯG1v[? ZFq7?Wh{9-?:= &Cnn^=ij;hR*>lʫ_PJN!?(k{݅{\L{@w%Æ:J槝`֛:~-A#ֿ5$տ~ZbYF~78?pcmHl,YN^8]4y~;Ưb//&Һ{?p5":[M?ߡ)#v2k'#v2k'wv2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2k'#v2$~/?'-ӧΎP)zOOs#8~;7\>*?6R~QPm&3ó#_/Iw f<?[mD'Ӕ}įW<?CbˍwtϦޚSwה 9+ϝmCրj+(cóU㏠DSo^.t^AOY'Q+ ?DdG~CB=xltVǒ=i, >og\7O{û7`)Sx~S 2E~ї8(~;^@EO~ {.P\DȰm!HH/ 8r)0QGذo RdٻB"妪|sϋ%v~S~/<9Aϧ*y~. _U)2?s-E~O>gwF~;kQKHUAۅ_N+(?%! ~Q^\?Ks 㛇;H+xgwF&/y{g+rʖQ;9Kߕ_Usv>U hh/? .X*6)&K4ϗt Ⱦݮ2~@X@bB-?eƔSWRE~o$*]DC~Q%m; 4^@/2*:,~fBGQS/reJ&F 5cp"mRDgn/$;_I \'mߜXGNO:M ҀhbJ fv¥<;S~da.~ Z$IiEGS >|cwXW $Os^Vv:4 Z~h;ȵ%w~+>_!)?sL>`%ڂrW ㇥Bfk[B#O9uxA9~!_IjUv[ }R+Oy/U8Sή&;巵s~߇} 579 ŢI{ g旕N]|[Evnu?"\;SdVw540[3+.ƥ- M0Y+z|-'1jd51Bguk~Uftd=R׹~ƅ _Tdz~ƚ@A}EW_Q p`__v V@$9/ 90{N)t90mTo56uA^B!ZUi S qUǏX,͟!,&/$g?pkG ].;~092BMv7ϯͮvhS`.[' I"V>>US: Y+-oԈ6aoL!# O3_a}9O`܅ uQjpG=9m7]VЩ<Ǻ`JQ/2҅3vs~ nk~a=wyUAѐj/H U'k9a.0*8oê'gn */hŇ?#gpbqQQ^mV:Q$+^U;9q~QFW8FQ#' ~1Z?啐d Јlr( bqy[Ϗ$2߮e/t_D~$$i Cm3sG m_?{>:~`spYG:=})Kvkf]SZUܟǪXؚW¶Jnc$,nnMS~ւfzoc[Zޭ-E{x _#Ѐmaxa]. L8 5*fgc7Οx6z3]}.zꇖXŜqgTpo~nfovy9[B.xb]_1~[m|CQFBp#)?[{X.8? jmtFye޴&C^ md5%tGMM$v^K y%ml~@G{wx@o 6ze$4i"Xg5d?,KRfmƆo%/%X l%A5GUHOǑL _|H0}.z[0UuG6`[/~e)IO k GzGu+.:2M ^ݳl_jDh#LE]c|Ԫ  c~Wy~aZ;WEk-G`vtۂSt'leE7W+3^UDt"!Gï2v xnM9R@1 Ǽ"p` Ԧ0p 7)?ïXd~ BČyJ_"73SާW/h۔֖[ _~ L FUݰh΀oBGaϟ Vp#Isd/UT7>ƆK߸H~6L+Z_ &։OIa\Jh ڗrq23;_0_ц_򻽹5}L$G`YL75{n=?s?ޣv߿3M_Y]]sg\?UUa  W|lY{)SUTmXW2E[}M W~ݬ^7ΖUZ b?-x[`ߞ_ VԆN>a42j%ۓ?~_8c#}yLs~0hrSj'k{:<~$06|[)^ҘbAW\_-KOӀ_TZ+,@XQ~x5~>e n&KNӀ[_nqJ `j$˛+E~{ gOӘN#/e T[1O,ŮIt/cJO2‡|K>&B}X=ſEO_nY5aans//?3^Sd$ g7)X]!ϝr&T]R~K6 q ̣]?6b#)7yb8?E{e~IJd xNH.훀 ;Y~a$DCoE+aCKe{GsgZ L $n-Twigo{O`dxdpk?TSq ?`/~1x}x?r9KL7 7_Aد9?{zDS6g΍;EHپj̠7|4Ueo_wŸ ?y/ 88w(^M7l{؉%? `@rZJasMב|Q'pt'(b!z噾$jmy~;]R=`N`a}^;f&Z磈0w18g'158n߭|,vJK_&&w`S)kv3-)9^GFx?KE~J/?֦Y2b7h%! Nn8hS/*9EfMUst̯pFC` Y5gܫEw<4ԤuI"+c8__)VGf_jg!$L";~~no;Ύ:ΏR~5He1?0m/ PGꕥ8NߔU7yX?V &ŤkX+|=Z"?:O8J7Kh+\.~|-¬ǯ*Ks ;vU'KK7wF:aQM:UN[ =[~"2;Y~Ϧ}Z~ kilYа0o%o!ĉŷӑoϽ f*+oN~o~eWN]#kuu`>Q \z ش Yp!׬z~߿^gCՎ緕k2~^?!߿߿@6 /,@%相3(ͥ/<"e:IS緿R~ʆ~7'aլ~U/*յ3;YL\OpN D.T'\!hV-hCXYJQDp%s5#N=\h>2.<嗟R~@`x<_05tUf9E&ynTPes࿈>F~E8׮|C% tdtn0|D~g4sa~#Zmڟ=2/;ͽ5tq ޟ>r:G*q~dBpPdxh=N+Jn`xiOy: ?1bz~^?ÊaRu/5nXa笾 a8981 k ^БɷOIq>i}iN ~.D#s0>?43#g)2?҅T<{;\p#GNL%.E4}.z[tϏI8rHFވ " ?$}m7r~iMib9?s ,~IF ޣ*z&D;9F?@)^;?Dht$P~!!G~ nX\׫V{ "?E,?1F캑m`nhLIZR/_6Hږ]~WV1!@H4a{ XB:UOcqsKAi6r<~ ѓpAhi0QDk Q~I6r\~$_0߇W~}I_YV\l?Hsf/۫4GߓC}vѽpHO&H~ &Y&-2h:d<_S~06rt~0T%!?PqBF< X5٣R tm~–MYh|^WEhqWBMC?W~da06}9 LI@@y9?EUGɇ^LF'~  Q$Gv,(U;VٽP`~h?{HM5,FED~L^>JV*wr*qqS9W?>m޼_B^dK<_'c@H qz-_Y*{ nkc@_D|7~<ޒ0lEM8~dsk/# ?:$۫*Oi.R]7~83:ş _F ds5/B)!ܔ߷o=xT)?=_y-* Qv(h~__j:73CӃly?P_GP߷ l>,o$#Z4+}K TMBow濙'F?"q~i#NCj4.Md#D>8!Z9m)KWW&rhrzBD\Yjt#_<-8o^(E=C/okgt#IgPT|7旛_t#=#A]-lT+4`raϹ̗r!`> s~3W`򘷏y,W"3]O_&!~e:~!tç&"<@4O^ykG֯֬3pY/wv/;uu }Bomϭ=;[b$ cNm7ŗ/owQ-)_p+DE-?@~ n~tbSJzi^BQD?ߺYAl?D$:uwby8KۚFzwFaQ&?;B8~Q>)euIo Ma~.!JUaRվF)Eھ"rQXt4k(ૠn$ uDq*h/Q".m,8xzpO)T~$L~}԰Mp7+Ke lkp> ۓ_W]3?iQEd,zy4竽JIU?! ,4 "`ߦFN C$ 3-{]iǏ]D* "ez_wnG~ \0?#(v'Dtō #3£0kk7nXau"UʯnZ)nd}rG M#N8N^eH#Uɢ=VJYƜoHeUSZ$$`=q#J ~qqgMkdgL ޖ2 [lg;̎+KeԂp'qxݰhDsC,Mc 5(y?@ݎzKh=ŏ -3aH[~}W[BKÛ[qiKF3pnj*򿭟1 YOW/72HmWlI?089Bk=QjI oږJb"Po~{)}noIc *dNoO'ǚ(w7mqu ^{)<: _ik%Qa??g~͋MղQ_43"!`qיdmq epZeV7Fx榤m'0^x{e[ZFF+-?ho6G ot'0W>stream 0 0 0 0 33 32 d1 33 0 0 32 0 0 cm BI /IM true /W 33 /H 32 /BPC 1 /D[1 0] /F/CCF /DP<> ID &a=A& oTl;MT#M4wiEvKm-a,1   EI endstream endobj 85 0 obj <> endobj 86 0 obj <> endobj 87 0 obj <> endobj 92 0 obj [/Indexed /DeviceRGB 255 <0000000000800000FF660066800000800080FF00FF9933660066CC0080808080 80FF80809999FFC0C0C0CCCCFF00FFFFCCFFFFFFFF00FFFFCCFFFFFF00000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000>]endobj 91 0 obj <>stream x흍(ݙSݝ[  =3(FxL&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2 ϓӿr&{)xpDDL&Y;E,MG*h2uZv4Ogw0qrLxtdz%8@Gas7:Wn qdzc³tQn3Zy 9bH3`mX飖8ݪq,0MDi0$GcC9fvD?ϡ8}GLV=piHIb:lĽȪ4=R0clqebw|EL&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2 և슘L+O緶 LdA dCS5T L]5ld60M&414p:>8&Ӄg L;p RYp70M7)]ǘb`.^GPi1e54i ǘb`Kv8*SKSw!pK1i:aK5$rT}R39"8FQ[Gkg6}ѹp=cy9ӎcn W1r 3\(:#>|#KhʊS x%k'rˉ8F 8HYJ%p4y!TQ*fᘚN8r8F (_ؿ}ѕ`R,YYspB8fT#YKe`N6ƿ5)45pč8f)p4y9M1isq20,1 qcL408V]۹cHñ1\FX? $aᘽ\ ǘh`NxQkS8FS4GǰPc/W)tQ9~7c^&D]qd-ǰ@Kф)az>/cL)4M [w1, f8J5y8̋5^SQ8 q~ ri8i4_XUc\ǣ>ts|j}q8eGяoD ;v6'Wq{i8^KGq8 2QN1e\ pf0t5*]d #LQ`8.WǰGRΙ&ZcH+*ZGG=lWYW}B\ǰHp^n8a!85\ ǘW%}tU5Gup uu)p$ cLXL9}2G) 1ǐTscHsBDq1hZ8u2c8.qdkRf=}힆ԟi8Y8j1,fu2m/2'h< ☭{1oW1&X4HeqZ8xQG"Eq)2'/lmpKdlq2'"57'X&LGq {G}+'} G,C->>?pEcƛf8.8f(68}tc GSUg Ç*W1Aͤñh+pdPO'C$uwH8ާ"*p +#p\Rw3q$;W8%/cH+j8^JqTEAN1I7so6tBa)p~ر8#j21I4K~ؑGWv">-ḪY 98u9Ǵ8UuO.p!xwH9spLk%a>!-p/`:ҶU8 h.X+_ǰLKjgq\W#7s70I8厞PCVcDmj8=q)=^@ թ1{X_G@>ϻ!8eq 8Ecq >r8.c8N(0­pX_ǐpN8vǜ98}/cX6'3qx<9$Q Qv }J8>e8NQ};oܝp߮j+n aZvhx |[* 8V4q%uNZ*pI :f DžT#=vtG:x| '-R,Bnq,G)Tpԓg8.$3q+ /M30z6a.~]ӓpLp 뒹cHQ+ sˎ_7GE i8E{ڔ*ѯ}DumsqLJ*}J^p đvMXW3iYCyY5S61y?G@rH&TI0x98~N{TS68b"qj4sN8ke'p7r|ZZesL17?bbL Fvt#}0H_GHp|719nAx; 9g6G>3qduǹ]GY-/&kWQtMGH[8~ƪ0]q}qu?1ߛ=cp _'Tt q}vEepkPoUUpk Z Gf̢2w$\ =!mk@, ǙEE.h%pܗY Ǽn4;zMGOs6+k#{ZY74i4t<|BḾ(9=q\[98Ǵr ǜI'VS$uƑq[j|ľ8}PaḔX8=cAtBѧPAXqd*q̽l3a)8)Y_ă I:^chT8浬_GjQh71mq,y(u㸯~8X0F.}qbl[#8fqOI\ ϙotlJrǎY3g8:Ǥ"o}pgc8&&JS4_85G1 qDHuiA-$閲'59Q >8R +ӎ8 9zW=T88ʼn7Z?N aE""8B~nį%M;hQ"98*#G2|gUeC`8r}8n Sp+xVk}⼁tjH;iCp,z83q̪R8ޮ(\rzHŪ8U<#Jk8NQ PIδcqQҧתXq_q(Ň8)OWEv` 4qLq_W0G2q<ƻicKSb?8ɢ@oOpGH連_#XtqbM8 4M5kph,qPIi ?GXJpV ,㘔t6 ichCp 4jw,8 G>:~0ކ8.ycC+Mq*,gۭoiv S~?s7G~쉘cR{xr[pd}q$Z7qnX%W@qOWQ8c8i_Ehʑ *ut Ee#%S=vox~@Ըqk)e.FuH_Z*e% /:GPbچ8cjSr qjXcJ1YK8Z3WS'cN0Fjp%b3c{#C Ǻ^.?ێ4S㾰_Y8Z2pn8R3I0ƯW3}Ggp48rՠ6'n $娦P%5I8f sta: Ƚ-j1{v1xG )\|Gr8,58a5s0QRQ!҈D혚O O8DVy)I=!G:Ka|+hH`|YqKu*98fxz8|GxϺ⸳͕.Mr@:dvPˢcV88CWw±h1qtS}ῨAu:ydNy'dad;x`p$]obpc ;~i!'Z}Crcb[pmH> 9zT;&=f"Hj b3+(vu6QD *OźBaʧovψV#qDE*cM^]:/G UXhVIctX-q k^vI 7p\CN8Ɣp^RKcM6w Q὞cGa8R28=-(Rjw+ݥμWݕ( ǹEŮc 8fѥM\ "a霵8s*B9?%' 3rdXJ>QGG Zฯn]DƑxF \qfVXc 3m882v!Vdh|mq"_c(]'mܺ;X% G6۸~`h"جn ZU+&/WLQjሎ9]c&&:Y!2Ǣxi8*b  I/o#Ȁ4o=Hypn? !~+3!E>]8J]BDGU+Dtυ w?`u*RJ& mH Kp|Y8=$;TH8aOŧ:) Ypj(}۶0s 㑞 L sXݱ+vLq .d}?S6M "$#9nd |8# n KH{;(~|#x[QGo ^Yq_#R t ~$zSQ&=?ܿȷ80OL2Da܀BSБ"0p.8 L11"z*ad΍ǧM٘%,_+1:snJɓ08~*RGacpӷ)p/}:;'Df@`[Jk?(ɛxgDc}|Zr'E:8BKx jfpDcqNQfAB`!&U(r=)U@0Aцy7׾^5^Lv(D/#0GqKSz=E GyBP>̟!IZLM2tw_.S'D %3qۀcUO1T8`kŴ-ٌ41`U銣vP" PѸ]7.Y8fʻ}#;9z$s GHt8ѐ}^cÙS_cc??xgU{>{AS\%P V~_nD24@8Nj8!qi#~X"ш9cѯ'{U6813q<S^M 4e.\2wG)4ק$f!V|m8<Cp\Qm2P GC k% GBqK˙ 3IM7IShic%m>?@8iʒ[~ǯc98Bsę8*:YUMp| #0 Dt[]l{q+9GUN,nNܴ ~)XUmt8/O{]LjF? gr ۾?ѾDr<}X>@EZ!s$c[*<_m4'Kuˀk 1[Q>W>03 4Ӓ1vQT;=oCAhLlRX 'KƲNQ9locH;=cޮ:V +E`*`$qҐ{vz Q8cx;{\~?%ɯ[zO32LQ=(~Gԫq {Qc͇^cb1Z燌⚨pL8܁V[Mp$[4sxPo)Y[&;c*MIrSE6eB9HZѫt&ȗN欎*Xa_٨90qKMìWiJX!8KЂnxr]U7 *fʁcqJ$vĢk1P:^8;rCr$;rEWWMSUW)\k?_xo$f8NvVb–n-d1j&XDuu5 :&_H @8n3/2&  QYJWE :i-LΪq{^8p]R{(p6>JwWE;'Ww#5z*AДD DpR ->)q]9f,Jrѯq4'Ln8Nq{tñFɳp9 8I4'<:6G/ztqMbeIy4'|d64KOҠ 8<24q[Og҈12[}IrTfDr倮c1eR?Jq< gX@r)t<ʘ{1OCc85Uu8!.d'-LJ-p}}U,[av]zEX0qqOX8c(ܧZq2׿`$*p|]ʂq8n @dۺHVL#0Foju1䯔84_r0[ݦ : Ծ9"]R5_d]ױGo K$myEp }ͷy7oW}ՄHU`SZxǟM:}qr:";_G*po^Nq;$ئG?+ՎDIG-AV.i b8Z0G|4SB ؞G$W3$]͛xW! ҩqYH%w'|9K7? QK_s ҇/K#LpgW'51!@~{*Kx_D?'6b0,N5w_%|B5jC84@)G*vfq8#Lxbt_q2|j]G._4pM 8eT: S9Ikg%Sc gBI/p}6_ sV'38Ap4±n>' 8ÓBKi2hB.q#җ`L t:repRF8&Ir(!pl<4)Y_E^nFr$aՅ嬌.[BLժ}p }X;c@RJ8m#1*q }tя(;  N_?~0C #/xS>LjpĨZtК껎edRun8e:G&)pLT;58::dEqaXO0p"F!v!؟YX15# 8Snג8!JxN1Iε\=tXH CraNMpT((.ːN|.d46U$00 l$tw:2.UAZEE"$ϔup 7PpL*0 83ށ8R5aG'OCQGџpē' 赎#ac|Le%O  p2KJp"7t&.JM#i3i8p!8>߿ @GǏc{pՎG2tpu41-qG+j7GUP*dc/& ǁް*;,kl5%$|(w &f>S9F5)pqԍ8*st4}q HVGG$bD%|8vCO))gcu4yPw'b$Y=d8V8Σ2X*NgCF}@re&m#/##f&OEmR3`#wwP8tIxp^`9#bqS&vEUM^Aňn G;Αo:/GIq ] Wcwn V5ڏxmL$ꁣdc)mXr@xqt./c9m8i E^N1GK4Ggp^;ĭsO|ḆoUpT,kJێd18X⨯4G-IGyxt A e+qtix,-.dk̒c$ 8P/W#  3&79H`ƍ1[}&r%?T xgQFMZu. <c`p\j_w1% 5n.aל@GxDdK_]b54 q}4dJ. !!C'BikqtٗT818u\=1#P̐ q$<#x܌qGp\(Nv*wME {2&F@djD DZh |*b)Hp7b(8>OJ{scE5HM v*97#*9ʣ)@8_V 5Z Hv1JDK=`u_z˳4 QZ8·KH r{$l .#* yE+8j5 G5ȼ3eLj41 ymw3a8r<#A###kQe[xվѬK&GG08&D&XDŽy֛rl'0/ R~rU#@pƭ0\b0)O 랖GO cQȒs8zG4c8Ral mBnrd]pGhX56M19)HgƜw?q\:v"Bst/;u_l; hI-Q̜ Q@q|-KL." pД[5AT ^28z7@%retnBoyd/Qg΋Y0nV9 Ȳ \FyjdtxxgSLYe%c kKeCӖXKb%[3 usi70۱FKmnq^40;522k=;u܄H-vo`?NRhia#VaNiY {C;8OLG31.q#|#%Np5M`x}g#DwM¢LvcG O#4;;&yb&3;zjNۡuUUȓȒmnQCJ_Npn `́]ےl c0|EvPxp\I@s.b&zbSsEN܈Uq#;Z 5yn&eZ(F)#?՜ )N׉%\ qEi]i;\SH7SGQªԄg]Fo%Mf*&%7p\O8@ Q GlzgoC&ZwIZ3+^l$l;VtV>]jD[^cXBg Yssc3 ÷OhC]*E[`dZ@xAR1'ݕ%%T]] tv8GqMw*>51E\$rjf0ru̐Sh1pSu'1!6ZQļ12H6и;x0c;WcBByb!2{:HbF@if¸pDif(3ɝR;|059]:hb;>a<1f"V]Oϐ=xSqA3384y`ZTUk1|եa eFKl;712VTn9iN@ixMPxMPc$ٻ[" -e/w |FPuƲYPmC9l0u =:[;]Z]ҢXeH!!R${Di5IX6e39GߣubOu9_la.*:!B5b6 GWU,w6j8SXm!l,(1΀F΢{-ΟBl fXA (vMTxXM:Ok"Jñ]-UfO|тX|Tt0G=aZM] &d H2xlmR˲+bc;crGc`Xb{xi8Pu_ۉanE#PJ}:^hTtJ9B>>C~09Z{:pI0Dk)3)7J\eS&ݘM2 \WbFp& Wj^=bRU*z^i Gv?sj8&>iT]1W*tK\̑Cdl*;Bk"j "ʰs B\e1*T*#q#m0CêjPSʝ\e2Xj~;xTcEPQwWxۣytx߬'&C.dBbFz\k:5x &rkTpl;Ķ?vzWU[CIR1֕oB`8'a [;trK%gb}uq Ǿ  ?Xǿp^t>dVM8t܀4u  xTۑd7TY5ep&?yHQ`P{#vEG2mI9t񁠴bW!)j EՆG5<AF6Нdr2UIV,!bU~E?i.ےK6tj[%B,(bŅ}Grc$w/=֙S]UiC0Ծ^Y/M6#hm=.tTXn=>|z4ͨSA!K$Mq Ix&Sq]QQl<" 1ǥre7W9I\̡ljg⊅sd8NUghBv(^Lok8&q[S4T! %!d%+]TuFD;/4- ^7K<\{41IqBGG8Lt;4Fr\]& IW],ju]EN%_rC! iĠ&ܪFi1M˫%:D$ő#N11Mco{<`+B$iԄp̑SIWAcl)lnE#HQ%Y{G:X(=r+f4/Led]^8}U[Af8ׄj#&Wʆd [+PW]yxH ʖW6_91,%i-_nkΣ.cdgyPky@"vبTM iS-cZÐXUC9rIe+o!  GXʹ҇ gb8V* h }dIǞlrb2~~ʊ&ÄdsUS<4Bc5HdOQM쒛L;xh'סյk2F4+(l2]L"Y0&C@>\#88SEAL/T.M4/%8_Jk4T]:z"AM1P(66pj8֔~#Q,m6a2# LG&>zL#RrTΨ&U;g2T1aLcP4L z ή2dZFk8L?=c8Lӕ~{d2͔~M&d2ukn2&i Gi&2Y9&:&d27:LUd}Gi&27:LedotL0L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2L&d2Ld)L endstream endobj 93 0 obj <> endobj 94 0 obj <> endobj 95 0 obj <> endobj 100 0 obj [/Indexed /DeviceRGB 15 <0000008080809999FFC0C0C0FFFFFF0000000000000000000000000000000000 00000000000000000000000000000000>]endobj 99 0 obj <>stream x[z5Af<5s0|I*UN0PY7Lh~@ @ @ @ @ @ @ @ @ @ @ Ƞn~8~kbۄf6FB" My*c=6Nq7{, 9ORǭW&ک}yK^Uz+wjۏM5ClX}q}8vKqaa?T h?Wi9xåv+Vaq|݌a{\ۋ6[?30xאS/GU2>N\?^AɃbx5zf*G6zdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdG51!gmgmRɣU=օAcy =jW X x=6zzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdp1n{8cJ8J8WXgG=^c e%G-\g|+us]NGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzd`׉۩W89Jpv=vրq;x葁葁葁葁葁葁葁葁葁葁葁葁葁葁葁葁葁a>qa\xz~58Uӑ exwmW8jz>g֏z>^`u9zdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdGzdp)=Wrm=Ncq~:lq شaشzM[o}Ϧĸl{ b_ b{w?s+j]A:cel;ZQXwدVv:]c-`G~5*0(;Wp@a@ \w0#1p|dV ~;x**=2pu ȠЯNX WnZ(E=V¾Vp~c%7<~kC9aGc c c :@%'q'w0sd葁*9 \w00=2p@ 0 .@ 2* `?F#UzdGfG$l]c]9a{d*=28c*8h*#=283><+TaJy_nQv (ݲkɻkpwc!bZ-T&ۤvT1f^p-|eLcs1?>%[w$"c2[$"ToxnwyweiKbRTLT<86N6a\*ʹTOssפJВ*&TkXsB.1aˋ'yKT .KfAG[򙬛V3H6fS. ilY'uW|7H^~W]Z]Ͱ[;g$$MEHlW'{<^\YͰEq]>tzpCg<&&_d=KRwOOW}[˖-!UqWMZtْNxfuOLx~I|jΧ>9i$\w#=2#=2#=2#=2#=2#=2#=2 BnCn15xvR]n[u{n;Q;=[<0o3"_q`z_mU]endobj 101 0 obj <>stream x[z*F_M?l u$̶enCbOg.Qn*)n-O-hqyZ6H ?yuR K[_b{1c"qY=ǵ n .qP,scsW:9y\tŜY?x['D3ǩ3ɭJގu|:c׮]m&үnqsxո;/oV>7Kq8װr~;Ѭ[ո~yU[.Ye; xt xͣ,xQjG 4xQSc`ߕi9G @}_t| fA{~sY֛q(ݶGy'y.q, x<Ǘo'x~nAcЯ5(`|#º~u0sxQR8s4(;WǢpA5`ݡ5ྜs+ s4`ݡ ?>F~/`0jG XwhCQBǎ}{F_GXT=z<@uqG~#P1T T d!~C>O?Ѐ#k:4sVQU hC00рGրGրrQpUQÁG W5}d AcI"%7>N cQЯQG jG _=Hү~GWO2 y fH쇇=v xx쒇KkgTo+_T3C!crP~ՙ9Ub|t\>q~;dЄy4͔XwOv׿Ξrl9GHѣ _8Y~GS=2񸇬~?1#%4Q}9tSLASB=35=΄Oq=<:1S].&غ{47*GF>x\>㖋GS=E)/yL=GcVW)[.#U x<}Kc]ORcW qQ1_C~Ujup ˂ǁ=?26GWk yUJ5TBʕlBꟳ@!ma 5x4zn!Λ㱏G|K&'Ґ$S#&y iH1Gi7!{S60qK^)r !> 9\&Ӑ4cI|S)K?x!\sA\pĤ4;*sC' Ļ' 2yL|$>~ǎu.y%|[AdH$1izLǞfOa!@?2eޛcӉ<-3(sb_?F ~lǧAabym:KFLӦqOT&l.UJr%gJ̝DH]a<rL"(i!5]Z16d,Muo6%.W)qoZh )I6_.#"0k$>!1Qt&;?Y+=GClYJ+SDzD1X{Oe\ݤcȬTj;&J^)KQ-KlHrB%'rJinYϥlK5цl*iy7tw>T)q3iYYlzk,J+Z}ZC,N+Wro3nuGZbBRż҃'cuGvUĻ8_MjRv3O]<3hHzb3>w|5]D؃+<.U0=c~t:2;4")ާWtt>_]:|TIz`hmxov}Ju"4s%86N+""y;~j2;xQCR>vNc0y?1} C7n'!qo M[CU[Ǥ8in˿3 ޗ~mq[wGp[\fDzd G 5xQ> endobj 104 0 obj <> endobj 105 0 obj <> endobj 110 0 obj [/Indexed /DeviceRGB 15 <0000008080809999FFC0C0C0FFFFFF0000000000000000000000000000000000 00000000000000000000000000000000>]endobj 109 0 obj <>stream xmz*E[L 9?Y2YOǖm@B05xQjK?:}oų>kk|nqXe+>L<\O;57]vh<29Cns8W&QŹe@tnqyׯ߮0dxQ9 KMx<s<xF1+x́Jhs<xF1+x́Jhs<xF1+x́Jhs<xF1+x́Jhs<xF1+]{\b=qYXNйG < s౒c$]{O囡֌s1+>]{̜j=ȮOzȗ| 9hA'٣xrxxϟ[)yr)ExRЯު"snUJ+~fhVJq0wx4+[R*[RyǭJ)ryG#{+H_v|#ʣucStc8GphWG<~<~:RVcx0ΩVίgt+_U:\enoCV<~<ϕrx,cxf8Kv]뽃|`)ãJv?\+rcx}dUU2XoW8x6R׶9F:zmWD"_1Q#9D"xԈQ#G5"xԈQ#G5"xԈQ#G5"xԈQ#G5"xԈQ#G5"xԈQ#G5"xԈQ#G5"xԈQ#rqYS18/uExGc/Y| . 9^~.hD/F1JgNj#Z_G>cG$V,T쇥÷ooֵѕ2-y<*xxTcm$rx\v֖r*BѾ!x<}/L\Jbx$౽Vx-T?G_7<&/xL*Vq*b<ǿ?O.7sI)?؛eY q$ʏyH#q|Dms-qc58s>.)Ώ5t#{>">q"I[:mN}9%نDu!a|\;jFuF!Q54d3xiQ>y5^~sC}E{s e 6$l8x^;S*'?Bv S~T:(]};t8Qxw>qy:-S#@0n"~qCQJqkS/zz\9zׁdF {M;E-E)i[JG,DrԌWxƣCh*iWW>Wrrpg1{LBw2yGҜdGƷƓI@iFL"ҽΔ4:Ӗdr4S3wXrt8x&?V8SJI**h, y99W܆/hIo1DR#CqIⲊ]t _xǫ$"8czT% [{_6am.ND Iu>$}puT%꽣[{<F:~kOpb[K?ӌ0qNd+`ޡ 5xQ]endobj 111 0 obj <>stream xm8QMgC~ @pG;]U-era  ^5FpQ#8jG5FpQ#8jG5FpQ#8jľs2ŗ[q9ϡ\lᡲCѯa1;,Xx<V!/+L:ptVP+ 8mc=^w0 ǿIyqz1{l|[q8 qQ.>~;y}a& 8|2g=8yqtm!:.gX0ql:_oI {1<:xtp:'߾7Ӄc)ȶxsظ\.9}q~lc47aX)O8Dǿi,{Mp|Ǹgɾv9:%qq z>ׇ=P>_ =e1o|v18e<$~2~~'fѻaSdq޽W1͸͙,_st8J$~g9G5FpQ#8jG5FpQ#8jG5FpQ#8jG5FpQ#8jG਑cG:I SpH+ )c18b9mO gWcENLJq"8΅c"5%gQ#8jG5FpQ#8jG5FpQ#ݧ:*8jG5FpQ#8jG5FpQ#8jG5FpQ#8jG5FG9~jct8sH4x?b9wh<8j~:8v0GpݡiG5FpQ#8jG5FpQ#8jG5FpQ#8jG5FpQ#8jG5FpQ#8jG5FpQ# ߣp^t.g.p;ȥ{{ȅcN_b<}ȹ\9~|p?.rQ#8jG5[ǟQfWxr1s??Cěk?apˎap8Ǧ[ތñ>xoc 8Ǧs[t xY?6Ka[X Syz|X{7Vwy}3ΊͶf~8ޚ'4_fuPVq}ǧרǓ*~l:W}b?6K/NNjtyNC:p< Xײc`c_ˎWұ^W{\ԙ=?ߏnQ㙴<[?p|?%KZԻmU8QU|rw[_pj|kVt_cuͪ3եSpIX;>cWY?<8cCoե_VBˑ RpܥpI 1'Ǧ/.EKY==qt-9.5yKG?cǎG ~8*8.+Ǿ>,Llm6=kvpI'0Ԯ-ɯ'DwxER;OTp~=PH',:-A}"i.ivAQhr.5u/B, 9mi<%O49f;!Չ>^m"\O4 tq]0.Bj:%Oa)%pɰ_6dt8<{3J5FpQ#8jG5FpQ#O?~,9_ hF= LJq#gRm>29M=YO<wqs|tOoWl'=du|WC> endobj 114 0 obj <> endobj 115 0 obj <> endobj 119 0 obj <> endobj 83 0 obj <>/FontMatrix[1 0 0 1 0 0]/FontBBox[0 0 33 32]/FirstChar 0/LastChar 0/Widths[ 35] /Subtype/Type3>> endobj 13 0 obj <> endobj 120 0 obj <> endobj 14 0 obj <> endobj 10 0 obj <> endobj 121 0 obj <> endobj 12 0 obj <> endobj 11 0 obj <> endobj 82 0 obj <> endobj 2 0 obj <>endobj xref 0 122 0000000000 65535 f 0000055290 00000 n 0000167526 00000 n 0000055100 00000 n 0000055666 00000 n 0000055518 00000 n 0000055338 00000 n 0000052116 00000 n 0000000015 00000 n 0000004139 00000 n 0000167100 00000 n 0000167398 00000 n 0000167321 00000 n 0000166863 00000 n 0000167029 00000 n 0000055412 00000 n 0000055442 00000 n 0000052276 00000 n 0000004159 00000 n 0000007390 00000 n 0000055813 00000 n 0000052420 00000 n 0000007411 00000 n 0000012355 00000 n 0000055867 00000 n 0000052564 00000 n 0000012376 00000 n 0000017249 00000 n 0000055910 00000 n 0000052708 00000 n 0000017270 00000 n 0000021362 00000 n 0000055953 00000 n 0000052852 00000 n 0000021383 00000 n 0000024899 00000 n 0000055996 00000 n 0000052996 00000 n 0000024920 00000 n 0000028195 00000 n 0000056039 00000 n 0000053140 00000 n 0000028216 00000 n 0000031832 00000 n 0000056082 00000 n 0000053284 00000 n 0000031853 00000 n 0000035709 00000 n 0000056125 00000 n 0000053428 00000 n 0000035730 00000 n 0000036724 00000 n 0000056168 00000 n 0000053572 00000 n 0000036744 00000 n 0000038333 00000 n 0000057814 00000 n 0000056211 00000 n 0000079967 00000 n 0000079999 00000 n 0000080031 00000 n 0000053767 00000 n 0000038354 00000 n 0000039826 00000 n 0000081677 00000 n 0000080074 00000 n 0000104450 00000 n 0000104482 00000 n 0000104514 00000 n 0000053962 00000 n 0000039847 00000 n 0000040808 00000 n 0000104697 00000 n 0000104557 00000 n 0000113212 00000 n 0000113244 00000 n 0000113276 00000 n 0000054157 00000 n 0000040828 00000 n 0000043537 00000 n 0000113448 00000 n 0000113308 00000 n 0000167470 00000 n 0000166688 00000 n 0000126133 00000 n 0000126372 00000 n 0000126404 00000 n 0000126436 00000 n 0000054360 00000 n 0000043558 00000 n 0000047828 00000 n 0000128091 00000 n 0000126488 00000 n 0000148516 00000 n 0000148548 00000 n 0000148580 00000 n 0000054555 00000 n 0000047849 00000 n 0000048069 00000 n 0000148764 00000 n 0000148623 00000 n 0000152845 00000 n 0000152704 00000 n 0000157175 00000 n 0000157223 00000 n 0000157269 00000 n 0000054753 00000 n 0000048089 00000 n 0000048312 00000 n 0000157443 00000 n 0000157302 00000 n 0000162164 00000 n 0000162023 00000 n 0000166515 00000 n 0000166563 00000 n 0000166611 00000 n 0000054953 00000 n 0000048333 00000 n 0000052094 00000 n 0000166644 00000 n 0000166955 00000 n 0000167193 00000 n trailer << /Size 122 /Root 1 0 R /Info 2 0 R >> startxref 167731 %%EOF iozone3_263/docs/Run_rules.doc000064400626570001775000000640001041702133100173160ustar00cappsrsnperf00000000000000ࡱ> /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_263/docs/IOzone_msword_98.doc000064400626570001775000006560001041702133000204640ustar00cappsrsnperf00000000000000ࡱ> [ ;bjbj xjjDl8888F/F/F/F/$j/^00000EEE]]]]]]]$^ aR]EIAxEEE]W88007]WWWE800]WE]W<W\R]z]00 0cm)F/Mj]z] ]0^r]kamVHkaz]W8888Iozone 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] [-+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 VxFS VX_DIRECT for all file operations. Tells the VXFS filesystem that all operations to the file are to bypass the buffer cache and go directly to disk. -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. -+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 CPU cache effect Buffer cache effect I/O performance after caches are exceeded Not measured CPU cache effect I/O performance after caches are exceeded Not measured CPU cache effect Not measured Buffer cache effect Buffer cache effect Anomaly #1 CPU cache effect Buffer cache effect Not measured Anomaly #2  ZvQYnr(Xb ""Z%f%((/+7+--//0000?5H5y6699C:E:::!;#;;;;;; <_<a<==>>5?9?@@!A#A]A_AAAAA5C7C8CTCDD:D56v6w6z66677P7778Y8889R9999`^999:B:C:F:::Q;;;; <^<_<b<<=n=====K>>>$`$^`^>>>4?5?:???G@@@@@ A!A$A\A]A`AAAA ByBB4C5CUC^`^UCCDDD9D:D=DDDDDDDDDEEEPFQFVFF GoGGH$$^$^^^`GGH HHH0I3IIIIIIIIIIJJJJJJJKKKKtLvLMMN"NTNVNNNOOQOzO|OQQQQ\Q]QRRRRRRSSS!SDSFSTTTT#U(U=UCUWU\UpUrUVVVV$W)W>WCWXW]WqWsWtWuW&X*XXXYYYYYZ Z Z ZZZ5dHH!H|HHHH/I0IGIIIII0JJJJJJJJFKKKKK@L^`$^@LsLtLwLL&M~MMMMNN"NSNTNWNNNNN>ONOOOROyOzO}O$^^^`}OO3PPPQQQwQRRRRSCSDSGSST`TTTTT#UoU`$^$^^^oUpUtUU-VVVVV$WpWqWvWW%X&X+XwXXXXYYYsYY$$^$^^`^Y Z ZZmZZZZZ[[[t[[[[[[[\\\~\\>]]]$^`^^ZZ[[[[[[[[\\^^y`~``````aaa=aIacc*c,cddAdNdffffNgOgTggg-h1h`hdhhhOiWiXi]jejfjkkm mmqq%r-r.r2r{{{{{{{{{|| mHnHu jJmHnHu j1U j U j|U jUjUmHnHu5\5P]O^^^^ _n_x`y`~``aO: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$xx  C `AHIOzone_msword_98_files\image002.gifb{ 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~) P\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%  C `AHIOzone_msword_98_files\image008.gifb0pѭC8t˭/u\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` i0@0 Normal_HmH sH tH 0@0 Heading 1$@&5<A@< Default Paragraph Font(>@( Title$a$CJ(<C@< Body Text Indent ^'R`r()7C;!#%)*,24'R`r()7CF ; z z z z z z z z z z z z z z z z z z "x2<ENWOcd]fgi%nwww;$;    a 8Ue< _  ( C Z t < r   ' XYZvwjt9:WXOPlmVWX!Y!"c##$$&-'.'=)))++,,,,Z.0=1>12v2w2z22233P3334Y4445R5555556B6C6F666Q7777 8^8_8b889n99999K:::::4;5;:;;;G<<<<< =!=$=\=]=`==== >y>>4?5?U??@@@9@:@=@@@@@@@@DAAAPBQBVBB CoCCDD!D|DDDD/E0EGEEEEE0FFFFFFFFFGGGGG@HsHtHwHH&I~IIIIJJ"JSJTJWJJJJJ>KNKOKRKyKzK}KK3LLLMMMwMNNNNOCODOGOOP`PPPPP#QoQpQtQQ-RRRRR$SpSqSvSS%T&T+TwTTTTUUUsUU V VVmVVVVVWWWtWWWWWWWXXX~XX>YYYOZZZZ [n[x\y\~\\]<]=]I]]^ ___o__```@`A`N`bbbbbbbNcOcacccc,d-d1d_d`ddddddddOeYeZe]fgfggggiiii$n.n3n4nfqgqrwwwwwwwwwwxxxxzRzvzzz|||| } }5}6}YZ[GHUVghՁց ,-8<0                                         0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 000000000000000000000000000000000000000000000000$3$3@$3$3$3@$3@$3$3$3$3$3$3$3@$3$3$30$3$3$3$3$3$3@$3$3$3$3$3@$3@$3$3$3@$3$3$3$3$3$3@$3$3$3$3@$3$3$3@$3$3$3$3$3$3$3$3$3@$3$3$3$3$3$3$3$3$3$3$3@$3$3$3@$3$3$3$3$3$3@$3@$300$3@$3@$3$3@$3$3$3$3@$3$3@$3@$3$30$3$3@$3$3$3$3$3@$3@$3$3@$3$3$3$3$3@$3$3$3$3@$3$3$3$3$3@$3@$3$3$3@$3$3$3@$3$3$3@$3$3$3$3$3@$3$3$3@$3@$3@$3@$3@$3@$3$3@$3$3$3$3@$3$3$3$3@$3@$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3@$3$3$3$3$3$3$3$3@$3$3$3$30$3$3$3$3$3$3$3$3$3$3$3$3@$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3@$3$3$3$3$3@$3$3$3$3$3$3$3$3$3$30$30$30$30$30$30$30$3000000000000000000$3$3$30$3$30$30$30$3$30$30$3$30$30$30$30$300$300$30$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$3$30$3$3$3$30$3$3$3$3$3$3$3$30$3$3000000000000000000000000000000000GZ ;DNTY l09>UCH@L}OoUY]@dOi{9;EGHIJKLMOPQRSUVWXZ[:F67b$V]KsdHcu[\b$[Bm=s]\b$эN3q‘U s)\b$,w#A*BnNXNԯ+:\b$9-#+axRT\b$'J: X~s \b$l)yն Z~{0#\b$.l"MI?FhT <\b$K;Bo 6_Z\@Z'6(  v  C FA.C:\tmp\old\MyHTML1.gif    C A\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\write_latency.gif""   C A\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\rewrite_latency.gif"#   C A\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\read_latency.gif"$   C A \\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\reread_latency.gif"%NB @ S DB    NB @ S DB    NB  S DB    NB  S DB    B    NB @ S DB     NB  S D B     NB  S D B    NB  @ S D B !     NB " S DB #      NB $@ S DB %     NB &@ S DB )     B *   !  NB +@ S D B ,   NB -@ S DNB 1 S DB 2   NB 3 S DB 4   NB 5 S DNB 6 S DB S  ?OePeQeReSeTeUeVe]f^f_f`fafbfcfdfii i i i i%n&n'n(n)n*n+n,n.n/n0n1nwwww;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 !4gs~   ( 2 C K P X Z b   < J r  ntv|~Z_<BNOSTlr>EZ!a!!!$$%#%& &/'7'''~(())**++++++,,,,k.o./ /o/t/0011?1D11111 222 2$2-2a2f23%3+393R3S33333]4g4w4444445*505A5f5r5177777777777 88f8j8883979<<<<<<3=?===$>+>N>U>>>>>??A?I?J?R?A@F@S@W@@@@@ AAA"A2A7ADAIASAXAAARBSBC+C0C>CCCUCZCjCCCCCCC%D)D\DfDEEEEFFFF)F.FSFYFoFuFFFHH}HHEIMIIIIIJJKKXM[M$N(NOOdOjOPPfQlQQQ1R;RgSmSSS/T5TTT VV(V/VLVRVXV_VWW[[ ]]S^Y^Y_____)`-`aab bbbbbTc`ckdrdddddddz{{C|L|||<'+  ( 2 C K Z b  < @ r w 2:@Fv{:>`$m$%$%&&''''~((**++_,j,,,/ /o/u/00112273;3R3S3a3b3f3g3p3q3z3{33333333333333333 4 4?4@44444444444 5555.5/5F5G5U5V5Y5\5d5e5w5x5}5~555556666Q7U77778f8k88888993989n9q999999999K:R:::::6;7;:;[;;;;;G<S<<<<<"=#=8=?===== >#>y>|>>>??@@A@G@@@@@DAIARBSBCC|D~DDD EEEEFFFFFGLGGGuHvHHH&I2IIIJJJJJJ>KAK{K|KKK3L:LLLXM[MwMMNNNNOOPPP^PPPPPPP$Q%QQQ-R0RRRRR%S&S'T(TwT{TTUUUsUyUmVqVVVVVtWxWWWXX%X2X~XX>YAYYYYYOZQZZZn[s[E\G\z\{\\\^ ^^^__o_q_C`D`bbbbQcRccccc/d0dddddgghhjjjjkk||<::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::UX55 CC-C/CACBCXCYCbbbd%n)n*n,n-n-n.n2n3n3n4n4n)o6opppppp||fg9< TC:\WINDOWS\Application Data\Microsoft\Word\AutoRecovery save of IOzone_msword_98.asd TC:\WINDOWS\Application Data\Microsoft\Word\AutoRecovery save of IOzone_msword_98.asd TC:\WINDOWS\Application Data\Microsoft\Word\AutoRecovery save of IOzone_msword_98.asd TC:\WINDOWS\Application Data\Microsoft\Word\AutoRecovery save of IOzone_msword_98.asd TC:\WINDOWS\Application Data\Microsoft\Word\AutoRecovery save of IOzone_msword_98.asd TC:\WINDOWS\Application Data\Microsoft\Word\AutoRecovery save of IOzone_msword_98.asd C:\tmp\IOzone_msword_98.docDonD:\IOzone_msword_98.docDon$C:\My Documents\IOzone_msword_98.doccapps'C:\tmp\Iozone_docs\IOzone_msword_98.doc0 d4 88^8`OJQJo(0 d<@||̖t33||;P@UnknownGz Times New Roman5Symbol3& z Arial;Wingdings"qhxxVj6!20d2IOzone Don CappscappsOh+'0\   $ 0<DLTIOzoneOzo Don Capps on  Normal.dotcapps.d2ppMicrosoft Word 9.0@F#@Ѻcm@ѺcmVj՜.+,D՜.+,@ hp  Hewlett-Packard62 IOzone Title 8@ _PID_HLINKSA6 Wi$IOzone_msword_98_files\image002.gif ej$IOzone_msword_98_files\image004.gif k$IOzone_msword_98_files\image006.gif  m$IOzone_msword_98_files\image008.gifmC:\tmp\old\MyHTML1.gifX| O\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\write_latency.gif= Q\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\rewrite_latency.gifHe N\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\read_latency.gif- P\\Rsnperf\rsnperf\WWW\projects\filesystem\nfs\hfs\4k\hp\gifs\reread_latency.gif  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcefghijklmnopqrstuvwxyz{|}~Root Entry FcmData M1TabledkaWordDocumentxSummaryInformation(DocumentSummaryInformation8CompObjjObjectPoolcmcm  FMicrosoft Word Document MSWordDocWord.Document.89qiozone3_263/docs/Iozone_ps.gz000064400626570001775000010010301041702133100171530ustar00cappsrsnperf00000000000000JN?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_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_