summaryrefslogtreecommitdiffstats
path: root/Python/pythonrun.c
Commit message (Expand)AuthorAgeFilesLines
* PEP 3147Barry Warsaw2010-04-171-0/+2
* * Replaces the internals of the subprocess module from fork through exec onGregory P. Smith2010-03-141-0/+26
* Merged revisions 78826 via svnmerge fromVictor Stinner2010-03-121-16/+9
* #4532: fixes to make 3.x compile on QNX 6.3.2 (reported by Matt Kraai)Andrew M. Kuchling2010-02-221-1/+1
* Issue #4486: When an exception has an explicit cause, do not print its implic...Antoine Pitrou2009-11-281-1/+1
* Merged revisions 75570 via svnmerge fromAntoine Pitrou2009-10-201-0/+32
* bytes -> bytearrayBenjamin Peterson2009-05-101-1/+1
* Issue #5915: Implement PEP 383, Non-decodable Bytes inMartin v. Löwis2009-05-051-16/+16
* Merged revisions 71152 via svnmerge fromMatthias Klose2009-04-041-2/+3
* The BDFL has retired! Long live the FLUFL (Friendly Language Uncle For Life)!Brett Cannon2009-04-011-0/+2
* Merged revisions 70908 via svnmerge fromJesse Noller2009-03-311-0/+1
* merge the io-c branch: C implementation of the io moduleBenjamin Peterson2009-03-041-1/+1
* ignore the coding cookie in compile(), exec(), and eval() if the source is a ...Benjamin Peterson2009-03-021-3/+11
* Followup of #4705: we can't skip the binary buffering layer for stdin because...Antoine Pitrou2009-01-261-2/+7
* Fix bug introduced in r68451: stdio must always be opened in line-buffered modeAntoine Pitrou2009-01-091-7/+15
* Issue #4705: Fix the -u ("unbuffered binary stdout and stderr") command-lineAntoine Pitrou2009-01-091-9/+76
* Merged revisions 68174 via svnmerge fromBenjamin Peterson2009-01-021-0/+2
* Merged revisions 68172-68173 via svnmerge fromMartin v. Löwis2009-01-021-3/+17
* Merged revisions 67295,67301-67302,67318,67330,67342-67343 via svnmerge fromAmaury Forgeot d'Arc2008-11-221-1/+1
* Merged revisions 67066 via svnmerge fromBenjamin Peterson2008-10-311-6/+12
* Issue 3723: Fixed initialization of subinterpretersChristian Heimes2008-10-301-0/+16
* Issue #4213: The file system encoding is now normalized by the codec subsyste...Christian Heimes2008-10-301-9/+32
* compile _bytesio and _stringio into the binary and initalize stdio before sit...Benjamin Peterson2008-09-051-2/+2
* #3663: extra DECREF on syntax errors.Antoine Pitrou2008-08-261-1/+4
* fix #3653 Python could segfault if invalid values were passed to sys.excepthookBenjamin Peterson2008-08-231-0/+7
* Rename PyUnicode_AsString -> _PyUnicode_AsString andMarc-André Lemburg2008-08-071-8/+8
* Merged revisions 65012,65035,65037-65040,65048,65057,65077,65091-65095,65097-...Georg Brandl2008-07-231-6/+7
* Merged revisions 64623,64640,64665,64687,64689-64690,64719,64721,64735,64742,...Georg Brandl2008-07-161-12/+12
* Make these files to compile again under Windows.Thomas Heller2008-07-151-2/+3
* implement chained exception tracebacksBenjamin Peterson2008-07-151-90/+161
* #2630: Implement PEP 3138.Georg Brandl2008-06-111-1/+1
* Issue 1342: Python could not start if installed in a directoryAmaury Forgeot d'Arc2008-06-111-1/+1
* Implement PEP 3121: new module initialization and finalization API.Martin v. Löwis2008-06-111-4/+2
* Move the codec decode type checks to bytes/bytearray.decode().Marc-André Lemburg2008-06-061-8/+4
* Fix uninitialized variable access, release memory.Martin v. Löwis2008-06-021-0/+3
* Forward-port PYTHONIOENCODING.Martin v. Löwis2008-06-021-6/+17
* Renamed PyString to PyBytesChristian Heimes2008-05-261-1/+1
* Renamed PyBytes to PyByteArrayChristian Heimes2008-05-261-2/+2
* Merged revisions 63066-63076,63079,63081-63085,63087-63097,63099,63101-63104 ...Alexandre Vassalotti2008-05-161-2/+2
* Merged revisions 62774-62775,62785,62787-62788 via svnmerge fromChristian Heimes2008-05-061-0/+1
* Added fast alternate io.BytesIO implementation and its test suite.Alexandre Vassalotti2008-05-061-2/+2
* Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,...Christian Heimes2008-04-131-60/+15
* Add a NEWS entry for issue2221.Amaury Forgeot d'Arc2008-04-101-2/+3
* Change command line processing API to use wchar_t.Martin v. Löwis2008-04-051-10/+20
* Issue2221: in Idle, exec('xx') raised a SystemError('error return without exc...Amaury Forgeot d'Arc2008-04-041-0/+7
* Merged revisions 61958-61959 via svnmerge fromChristian Heimes2008-03-261-4/+2
* Merged revisions 61954,61956-61957 via svnmerge fromChristian Heimes2008-03-261-0/+1
* Merged revisions 61952-61953 via svnmerge fromChristian Heimes2008-03-261-5/+18
* Issue2297: Fix a stack overflow in Windows caused by -v and -vv. When python...Trent Nelson2008-03-191-3/+17
* Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,...Christian Heimes2008-02-191-2/+8
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the files COPYING and Copyright.html.  COPYING can be found at the root   *
 * of the source code distribution tree; Copyright.html can be found at the  *
 * root level of an installed copy of the electronic HDF5 document set and   *
 * is linked from the top-level documents page.  It can also be found at     *
 * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
 * access to either file, you may request a copy from help@hdfgroup.org.     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 * Programmer:	Raymond Lu <slu@ncsa.uiuc.edu>
 *		Friday, Oct 3, 2004
 *
 * Purpose:	Tests performance of metadata
 */

#include "h5test.h"

#ifdef H5_HAVE_PARALLEL
#define MAINPROCESS	(!mpi_rank)	/* define process 0 as main process */
#endif /*H5_HAVE_PARALLEL*/

/* File_Access_type bits */
#define FACC_DEFAULT	0x0	/* serial as default */
#define FACC_MPIO	0x1	/* MPIO */

/* Which test to run */
int RUN_TEST = 0x0;     /* all tests as default */
int TEST_1   = 0x1;     /* Test 1 */
int TEST_2   = 0x2;     /* Test 2 */
int TEST_3   = 0x4;     /* Test 3 */


const char *FILENAME[] = {
    "meta_perf_1",
    "meta_perf_2",
    "meta_perf_3",
    NULL
};

/* Default values for performance. Can be changed through command line options */
int 	NUM_DSETS = 16;
int 	NUM_ATTRS = 8;
int 	BATCH_ATTRS = 2;
hbool_t flush_dset = FALSE;
hbool_t flush_attr = FALSE;
int 	nerrors = 0;			/* errors count */
hid_t	fapl;

/* Data space IDs */
hid_t	space;
hid_t	small_space;

/* Performance data */
typedef struct p_time {
    double total;
    double avg;
    double max;
    double min;
    double start;
    char   func[32];
} p_time;

/*Test file access type for parallel.  MPIO as default */
int facc_type = FACC_DEFAULT;

double  retrieve_time(void);
void    perf(p_time *perf_t, double start_t, double end_t);
void    print_perf(p_time, p_time, p_time);


/*-------------------------------------------------------------------------
 * Function:	parse_options
 *
  Purpose:	Parse command line options
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static int
parse_options(int argc, char **argv)
{
    int t;

    /* Use default values */
    if(argc==1)
	return(0);

    while (--argc){
	if (**(++argv) != '-'){
	    break;
	}else{
	    switch(*(*argv+1)){
                case 'h':   /* Help page */
                            return(1);

		case 'd':   /* Number of datasets */
                            NUM_DSETS = atoi((*argv+1)+1);
			    if (NUM_DSETS < 0){
				nerrors++;
				return(1);
			    }
			    break;

		case 'a':   /* Number of attributes per dataset */
                            NUM_ATTRS = atoi((*argv+1)+1);
			    if (NUM_ATTRS < 0){
				nerrors++;
				return(1);
			    }
			    break;

		case 'n':   /* Number of attributes to be created in batch */
                            BATCH_ATTRS = atoi((*argv+1)+1);
			    if (BATCH_ATTRS < 0){
				nerrors++;
				return(1);
			    }
			    break;

		case 'm':   /* Use the MPI-IO driver */
			    facc_type = FACC_MPIO;
			    break;

                case 'f':   /* Call H5Fflush for each dataset or attribute */
                            if(!strcmp("a", (*argv+2)))
                                flush_attr = TRUE;
                            else if(!strcmp("d", (*argv+2)))
                                flush_dset = TRUE;
                            else {
                                nerrors++;
                                return(1);
                            }
                            break;

		case 't':   /* Which test to run */
                            t = atoi((*argv+1)+1);
			    if (t < 1 || t > 3){
				nerrors++;
				return(1);
			    }
                            if(t == 1)
                                RUN_TEST |= TEST_1;
                            else if(t == 2)
                                RUN_TEST |= TEST_2;
                            else
                                RUN_TEST |= TEST_3;

			    break;

 		default:    nerrors++;
			    return(1);
	    }
	}
    } /*while*/

    /* Check valid values */
#ifndef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO)
    {
        nerrors++;
        return(1);
    }
#endif /*H5_HAVE_PARALLEL*/

    if(NUM_ATTRS && !BATCH_ATTRS)
        NUM_ATTRS = 0;

    if(!NUM_ATTRS && BATCH_ATTRS)
        BATCH_ATTRS = 0;

    if(!NUM_DSETS) {
        nerrors++;
        return(1);
    }

    if(NUM_ATTRS && BATCH_ATTRS) {
        if(BATCH_ATTRS > NUM_ATTRS || NUM_ATTRS % BATCH_ATTRS) {
	    nerrors++;
            return(1);
        }
    }

    return(0);
}


/*-------------------------------------------------------------------------
 * Function:	usage
 *
  Purpose:	Prints help page
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static void
usage(void)
{
    printf("Usage: perf_meta [-h] [-m] [-d<num_datasets>]"
           "[-a<num_attributes>]\n"
           "\t[-n<batch_attributes>] [-f<option>] [-t<test>]\n");
    printf("\t-h"
	"\t\t\thelp page.\n");
    printf("\t-m"
	"\t\t\tset MPIO as the file driver when parallel HDF5\n"
        "\t\t\t\tis enabled.  -m must be specified\n"
        "\t\t\t\twhen running parallel program.\n");
    printf("\t-d<num_datasets>"
	"\tset number of datasets for meta data \n"
        "\t\t\t\tperformance test\n");
    printf("\t-a<num_attributes>"
        "\tset number of attributes per dataset for meta \n"
        "\t\t\t\tdata performance test.\n");
    printf("\t-n<batch_attributes>"
	"\tset batch number of attributes for dataset \n"
        "\t\t\t\tfor meta data performance test.\n");
    printf("\t-f<option>"
	"\t\tflush data to disk after closing a dataset \n"
        "\t\t\t\tor attribute.  Valid options are \"d\" for \n"
        "\t\t\t\tdataset, \"a\" for attribute.  Disabled is \n"
        "\t\t\t\tthe default.\n");
    printf("\t-t<tests>"
	"\t\trun specific test.  Give only one number each \n"
        "\t\t\t\ttime. i.e. \"-t1 -t3\" will run test 1 and 3. \n"
        "\t\t\t\tDefault is all three tests.  The 3 tests are: \n\n"
        "\t\t\t\t1. Create <num_attributes> attributes for each \n"
        "\t\t\t\t   of <num_datasets> existing datasets.\n"
        "\t\t\t\t2. Create <num_attributes> attributes for each \n"
        "\t\t\t\t   of <num_datasets> new datasets.\n"
        "\t\t\t\t3. Create <batch_attributes> attributes for \n"
        "\t\t\t\t   each of <num_dataset> new datasets for \n"
        "\t\t\t\t   <num_attributes>/<batch_attributes> times.\n");
}


/*-------------------------------------------------------------------------
 * Function:	create_dspace
 *
 * Purpose:	Attempts to create data space.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
create_dspace(void)
{
    hsize_t	dims[2];
    hsize_t	small_dims[2];

    /* Create the data space */
    dims[0] = 256;
    dims[1] = 512;
    if((space = H5Screate_simple(2, dims, NULL)) < 0)
	    goto error;

    /* Create a small data space for attributes */
    small_dims[0] = 16;
    small_dims[1] = 8;
    if((small_space = H5Screate_simple(2, small_dims, NULL)) < 0)
	    goto error;

    return 0;

error:
    return -1;
}


/*-------------------------------------------------------------------------
 * Function:	create_dsets
 *
 * Purpose:	Attempts to create some datasets.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
create_dsets(hid_t file)
{
    hid_t	dataset;
    char	dset_name[32];
    int		i;

    /*
     * Create a dataset using the default dataset creation properties.
     */
    for(i = 0; i < NUM_DSETS; i++) {
	sprintf(dset_name, "dataset %d", i);
    	if((dataset = H5Dcreate2(file, dset_name, H5T_NATIVE_DOUBLE, space,
                H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
            goto error;

    	if(H5Dclose(dataset) < 0)
            goto error;
    } /* end for */

    return 0;

error:
    return -1;

}


/*-------------------------------------------------------------------------
 * Function:	create_attrs_1
 *
 * Purpose:	Attempts to create all attributes for each existing dataset.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
create_attrs_1(void)
{
    hid_t	file, dataset, attr;
    char	filename[128];
    char	dset_name[64];
    char	attr_name[128];
    int		i, j;
    p_time      attr_t  = {0, 0, 0, 1000000, 0, ""};
    p_time      open_t  = {0, 0, 0, 1000000, 0, "H5Dopen2"};
    p_time      close_t = {0, 0, 0, 1000000, 0, ""};

#ifdef H5_HAVE_PARALLEL
    /* need the rank for printing data */
    int         mpi_rank;
    if(facc_type == FACC_MPIO)
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
#endif /*H5_HAVE_PARALLEL*/

    h5_fixname(FILENAME[0], fapl, filename, sizeof filename);

    if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT,
	fapl)) < 0)
	goto error;

    if(create_dsets(file) < 0)
	goto error;

    /*
     * Create all(user specifies the number) attributes for each dataset
     */
    for(i = 0; i < NUM_DSETS; i++) {
	sprintf(dset_name, "dataset %d", i);
        open_t.start = retrieve_time();
	if((dataset = H5Dopen2(file, dset_name, H5P_DEFAULT)) < 0)
		goto error;
	perf(&open_t, open_t.start, retrieve_time());

	for(j = 0; j < NUM_ATTRS; j++) {
            sprintf(attr_name, "all attrs for each dset %d", j);
            attr_t.start = retrieve_time();
            if((attr = H5Acreate2(dataset, attr_name, H5T_NATIVE_DOUBLE,
                    small_space, H5P_DEFAULT, H5P_DEFAULT)) < 0)
                goto error;
            if(H5Aclose(attr) < 0)
                goto error;
            perf(&attr_t, attr_t.start, retrieve_time());
            if(flush_attr && H5Fflush(file, H5F_SCOPE_LOCAL) < 0)
                goto error;
    	} /* end for */

	close_t.start = retrieve_time();
    	if(H5Dclose(dataset) < 0)
            goto error;
	perf(&close_t, close_t.start, retrieve_time());
        if(flush_dset && H5Fflush(file,  H5F_SCOPE_LOCAL) < 0)
            goto error;
    } /* end for */

    if(facc_type == FACC_MPIO) {
#ifdef H5_HAVE_PARALLEL
        MPI_Barrier(MPI_COMM_WORLD);
#endif /*H5_HAVE_PARALLEL*/
    }

#ifdef H5_HAVE_PARALLEL
    if (facc_type == FACC_DEFAULT || (facc_type != FACC_DEFAULT && MAINPROCESS)) /* only process 0 reports */
#endif /*H5_HAVE_PARALLEL*/
    {
        /* Calculate the average time */
        open_t.avg  = open_t.total / NUM_DSETS;
        close_t.avg = close_t.total / NUM_DSETS;
        if(NUM_ATTRS)
            attr_t.avg  = attr_t.total / (NUM_ATTRS*NUM_DSETS);

        /* Print out the performance result */
        fprintf(stderr, "1.  Create %d attributes for each of %d existing datasets\n",
            NUM_ATTRS, NUM_DSETS);
        print_perf(open_t, close_t, attr_t);
    }

    if (H5Fclose(file) < 0) goto error;

    return 0;

error:
    return -1;
}


/*-------------------------------------------------------------------------
 * Function:	create_attrs_2
 *
 * Purpose:	Attempts to create all attributes for each new dataset.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
create_attrs_2(void)
{
    hid_t	file, dataset, attr;
    char	filename[128];
    char	dset_name[64];
    char	attr_name[128];
    int		i, j;
    p_time      attr_t  = {0, 0, 0, 1000000, 0, ""};
    p_time      create_t  = {0, 0, 0, 1000000, 0, "H5Dcreate2"};
    p_time      close_t = {0, 0, 0, 1000000, 0, ""};

#ifdef H5_HAVE_PARALLEL
    /* need the rank for printing data */
    int         mpi_rank;
    if(facc_type == FACC_MPIO)
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
#endif /*H5_HAVE_PARALLEL*/

    h5_fixname(FILENAME[1], fapl, filename, sizeof filename);

    if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
	goto error;

    /*
     * Create all(user specifies the number) attributes for each new dataset
     */
    for(i = 0; i < NUM_DSETS; i++) {
	sprintf(dset_name, "dataset %d", i);
        create_t.start = retrieve_time();
   	if((dataset = H5Dcreate2(file, dset_name, H5T_NATIVE_DOUBLE,
                space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
            goto error;
	perf(&create_t, create_t.start, retrieve_time());

	for(j = 0; j < NUM_ATTRS; j++) {
            sprintf(attr_name, "all attrs for each dset %d", j);
            attr_t.start = retrieve_time();
            if((attr = H5Acreate2(dataset, attr_name, H5T_NATIVE_DOUBLE,
                    small_space, H5P_DEFAULT, H5P_DEFAULT)) < 0)
                goto error;
            if(H5Aclose(attr) < 0)
                goto error;
            perf(&attr_t, attr_t.start, retrieve_time());
            if(flush_attr && H5Fflush(file,  H5F_SCOPE_LOCAL) < 0)
                goto error;
	} /* end for */

	close_t.start = retrieve_time();
    	if(H5Dclose(dataset) < 0)
            goto error;
	perf(&close_t, close_t.start, retrieve_time());
        if(flush_dset && H5Fflush(file,  H5F_SCOPE_LOCAL) < 0)
            goto error;
    } /* end for */

#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO)
        MPI_Barrier(MPI_COMM_WORLD);
#endif /*H5_HAVE_PARALLEL*/

#ifdef H5_HAVE_PARALLEL
    /* only process 0 reports if parallel */
    if (facc_type == FACC_DEFAULT || (facc_type != FACC_DEFAULT && MAINPROCESS))
#endif /*H5_HAVE_PARALLEL*/
    {
        /* Calculate the average time */
        create_t.avg = create_t.total / NUM_DSETS;
        close_t.avg  = close_t.total / NUM_DSETS;
        if(NUM_ATTRS)
            attr_t.avg = attr_t.total / (NUM_ATTRS*NUM_DSETS);

        /* Print out the performance result */
        fprintf(stderr, "2.  Create %d attributes for each of %d new datasets\n",
            NUM_ATTRS, NUM_DSETS);
        print_perf(create_t, close_t, attr_t);
    }

    if (H5Fclose(file) < 0) goto error;

    return 0;

error:
    return -1;
}


/*-------------------------------------------------------------------------
 * Function:	create_attrs_3
 *
 * Purpose:	Attempts to create some attributes for each dataset in a
 * 		loop.
 *
 * Return:	Success:	0
 *
 *		Failure:	-1
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
create_attrs_3(void)
{
    hid_t	file, dataset, attr;
    char	filename[128];
    char	dset_name[64];
    char	attr_name[128];
    int		loop_num;
    int		i, j, k;
    p_time      attr_t  = {0, 0, 0, 1000000, 0, ""};
    p_time      open_t  = {0, 0, 0, 1000000, 0, "H5Dopen2"};
    p_time      close_t = {0, 0, 0, 1000000, 0, ""};

#ifdef H5_HAVE_PARALLEL
    /* need the rank for printing data */
    int         mpi_rank;
    if(facc_type == FACC_MPIO)
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
#endif /*H5_HAVE_PARALLEL*/

    h5_fixname(FILENAME[2], fapl, filename, sizeof filename);

    if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT,
	fapl)) < 0)
	goto error;

    if(create_dsets(file) < 0)
	goto error;

    /*
     * Create some(user specifies the number) attributes for each dataset
     * in a loop
     */
    loop_num = NUM_ATTRS/BATCH_ATTRS;

    for(i = 0; i < loop_num; i++) {
    	for(j = 0; j < NUM_DSETS; j++) {
            sprintf(dset_name, "dataset %d", j);
            open_t.start = retrieve_time();
            if((dataset = H5Dopen2(file, dset_name, H5P_DEFAULT)) < 0)
                goto error;
            perf(&open_t, open_t.start, retrieve_time());

            for(k = 0; k < BATCH_ATTRS; k++) {
                sprintf(attr_name, "some attrs for each dset %d %d", i, k);
                attr_t.start = retrieve_time();
                if((attr = H5Acreate2(dataset, attr_name, H5T_NATIVE_DOUBLE,
                        small_space, H5P_DEFAULT, H5P_DEFAULT)) < 0)
                    goto error;
                if(H5Aclose(attr) < 0)
                    goto error;
                perf(&attr_t, attr_t.start, retrieve_time());
                if(flush_attr && H5Fflush(file,  H5F_SCOPE_LOCAL) < 0)
                    goto error;
            } /* end for */

            close_t.start = retrieve_time();
            if(H5Dclose(dataset) < 0)
                goto error;
            perf(&close_t, close_t.start, retrieve_time());
            if(flush_dset && H5Fflush(file,  H5F_SCOPE_LOCAL) < 0)
                goto error;
    	} /* end for */
    } /* end for */

#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO)
        MPI_Barrier(MPI_COMM_WORLD);
#endif /*H5_HAVE_PARALLEL*/

#ifdef H5_HAVE_PARALLEL
    /* only process 0 reports if parallel */
    if (facc_type == FACC_DEFAULT || (facc_type != FACC_DEFAULT && MAINPROCESS))
#endif /*H5_HAVE_PARALLEL*/
    {
        /* Calculate the average time */
        open_t.avg = open_t.total / (loop_num*NUM_DSETS);
        close_t.avg = close_t.total / (loop_num*NUM_DSETS);
        attr_t.avg = attr_t.total / (NUM_ATTRS*NUM_DSETS);

        /* Print out the performance result */
        fprintf(stderr, "3.  Create %d attributes for each of %d existing datasets for %d times\n",
            BATCH_ATTRS, NUM_DSETS, loop_num);
        print_perf(open_t, close_t, attr_t);
    }

    if (H5Fclose(file) < 0) goto error;

    return 0;

error:
    return -1;
}


/*-------------------------------------------------------------------------
 * Function:	retrieve_time
 *
 * Purpose:     Returns time in seconds, in a double number.
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
double retrieve_time(void)
{
#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_DEFAULT) {
#endif /*H5_HAVE_PARALLEL*/
        struct timeval t;
        HDgettimeofday(&t, NULL);
        return ((double)t.tv_sec + (double)t.tv_usec / 1000000);
#ifdef H5_HAVE_PARALLEL
    } else {
        return MPI_Wtime();
    }
#endif /*H5_HAVE_PARALLEL*/
}


/*-------------------------------------------------------------------------
 * Function:	perf
 *
 * Purpose:	Calculate total time, maximal and minimal time of
 *              performance.
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
void perf(p_time *perf_t, double start_t, double end_t)
{
	double t = end_t - start_t;

#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO) {
        double reduced_t;
        double t_max, t_min;
        int    mpi_size, mpi_rank;

        MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
        MPI_Barrier(MPI_COMM_WORLD);

        MPI_Reduce(&t, &reduced_t, 1, MPI_DOUBLE, MPI_SUM, 0,
                MPI_COMM_WORLD);
        reduced_t /= mpi_size;

        MPI_Reduce(&t, &t_max, 1, MPI_DOUBLE, MPI_MAX, 0,
                MPI_COMM_WORLD);
        MPI_Reduce(&t, &t_min, 1, MPI_DOUBLE, MPI_MIN, 0,
                MPI_COMM_WORLD);

        if (MAINPROCESS) {
            perf_t->total += reduced_t;

	    if(t_max > perf_t->max)
		perf_t->max = t_max;
	    if(t_min < perf_t->min)
		perf_t->min = t_min;
        }
    } else
#endif /*H5_HAVE_PARALLEL*/
    {
	perf_t->total += t;

	if(t > perf_t->max)
		perf_t->max = t;
	if(t < perf_t->min)
		perf_t->min = t;
    }
}


/*-------------------------------------------------------------------------
 * Function:	print_perf
 *
 * Purpose:	Print out performance data.
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
void print_perf(p_time open_t, p_time close_t, p_time attr_t)
{
    fprintf(stderr, "\t%s:\t\tavg=%.6fs;\tmax=%.6fs;\tmin=%.6fs\n",
		open_t.func, open_t.avg, open_t.max, open_t.min);
    fprintf(stderr, "\tH5Dclose:\t\tavg=%.6fs;\tmax=%.6fs;\tmin=%.6fs\n",
		close_t.avg, close_t.max, close_t.min);
    if(NUM_ATTRS)
        fprintf(stderr, "\tH5A(create & close):\tavg=%.6fs;\tmax=%.6fs;\tmin=%.6fs\n",
		attr_t.avg, attr_t.max, attr_t.min);
}


/*-------------------------------------------------------------------------
 * Function:	main
 *
 * Purpose:	Tests
 *
 * Return:	Success:	exit(0)
 *
 *		Failure:	exit(1)
 *
 * Programmer:	Raymond Lu
 *		Friday, Oct 3, 2003
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
int
main(int argc, char **argv)
{
#ifdef H5_HAVE_PARALLEL
    int mpi_size, mpi_rank;				/* mpi variables */
#endif /*H5_HAVE_PARALLEL*/

    if(parse_options(argc, argv) != 0) {
       usage();
       return 0;
    }

#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO) {
        MPI_Init(&argc, &argv);
        MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
    }
#endif /*H5_HAVE_PARALLEL*/

#ifdef H5_HAVE_PARALLEL
    if (facc_type == FACC_DEFAULT || (facc_type != FACC_DEFAULT && MAINPROCESS))
#endif /*H5_HAVE_PARALLEL*/
        fprintf(stderr, "\t\tPerformance result of metadata for datasets and attributes\n\n");

    fapl = H5Pcreate (H5P_FILE_ACCESS);
#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO)
        H5Pset_fapl_mpio(fapl, MPI_COMM_WORLD, MPI_INFO_NULL);
#endif /*H5_HAVE_PARALLEL*/

    nerrors += create_dspace() < 0 	?1:0;

    if((RUN_TEST & TEST_1) || !RUN_TEST)
        nerrors += create_attrs_1() < 0 	?1:0;
    if((RUN_TEST & TEST_2) || !RUN_TEST)
        nerrors += create_attrs_2() < 0 	?1:0;
    if(((RUN_TEST & TEST_3) || !RUN_TEST) && BATCH_ATTRS && NUM_ATTRS)
        nerrors += create_attrs_3() < 0 	?1:0;

    if (H5Sclose(space) < 0) goto error;
    if (H5Sclose(small_space) < 0) goto error;

    h5_clean_files(FILENAME, fapl);

#ifdef H5_HAVE_PARALLEL
    if(facc_type == FACC_MPIO)
        /* MPI_Finalize must be called AFTER H5close which may use MPI calls */
        MPI_Finalize();
#endif /*H5_HAVE_PARALLEL*/

    if (nerrors) goto error;
#ifdef H5_HAVE_PARALLEL
    if (facc_type != FACC_DEFAULT && MAINPROCESS)
#endif /*H5_HAVE_PARALLEL*/
        printf("All metadata performance tests passed.\n");

    return 0;

 error:
    nerrors = MAX(1, nerrors);
#ifdef H5_HAVE_PARALLEL
    if (facc_type != FACC_DEFAULT && MAINPROCESS)
#endif /*H5_HAVE_PARALLEL*/
        printf("***** %d PERFORMANCE TEST%s FAILED! *****\n",
	   nerrors, 1 == nerrors ? "" : "S");

    return 1;
}