Example #1
0
static svn_error_t *
svn_fs_bdb__close_internal(bdb_env_t *bdb)
{
  svn_error_t *err = SVN_NO_ERROR;

  if (--bdb->refcount != 0)
    {
      /* If the environment is panicked and automatic recovery is not
         enabled, return an appropriate error. */
#if !SVN_BDB_AUTO_RECOVER
      if (svn_atomic_read(&bdb->panic))
        err = svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
                                db_strerror(DB_RUNRECOVERY));
#endif
    }
  else
    {
      /* If the bdb cache has been set to NULL that means we are
         shutting down, and the pool that holds the bdb cache has
         already been destroyed, so accessing it here would be a Bad
         Thing (tm) */
      if (bdb_cache)
        apr_hash_set(bdb_cache, &bdb->key, sizeof bdb->key, NULL);
      err = bdb_close(bdb);
    }
  return svn_error_trace(err);
}
Example #2
0
static svn_error_t *
svn_fs_bdb__open_internal(bdb_env_baton_t **bdb_batonp,
                          const char *path,
                          u_int32_t flags, int mode,
                          apr_pool_t *pool)
{
  bdb_env_key_t key;
  bdb_env_t *bdb;
  svn_boolean_t panic;

  /* We can safely discard the open DB_CONFIG file handle.  If the
     environment descriptor is in the cache, the key's immutability is
     guaranteed.  If it's not, we don't care if the key changes,
     between here and the actual insertion of the newly-created
     environment into the cache, because no other thread can touch the
     cache in the meantime. */
  SVN_ERR(bdb_cache_key(&key, NULL, path, pool));

  bdb = bdb_cache_get(&key, &panic);
  if (panic)
    return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
                            db_strerror(DB_RUNRECOVERY));

  /* Make sure that the environment's open flags haven't changed. */
  if (bdb && bdb->flags != flags)
    {
      /* Handle changes to the DB_PRIVATE flag specially */
      if ((flags ^ bdb->flags) & DB_PRIVATE)
        {
          if (flags & DB_PRIVATE)
            return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
                                    "Reopening a public Berkeley DB"
                                    " environment with private attributes");
          else
            return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
                                    "Reopening a private Berkeley DB"
                                    " environment with public attributes");
        }

      /* Otherwise return a generic "flags-mismatch" error. */
      return svn_error_create(SVN_ERR_FS_BERKELEY_DB, NULL,
                              "Reopening a Berkeley DB environment"
                              " with different attributes");
    }

  if (!bdb)
    {
      svn_error_t *err;

      SVN_ERR(create_env(&bdb, path, svn_pool_create(bdb_cache_pool)));
      err = bdb_open(bdb, flags, mode);
      if (err)
        {
          /* Clean up, and we can't do anything about returned errors. */
          svn_error_clear(bdb_close(bdb));
          return svn_error_trace(err);
        }

      apr_hash_set(bdb_cache, &bdb->key, sizeof bdb->key, bdb);
      bdb->flags = flags;
      bdb->refcount = 1;
    }
  else
    {
      ++bdb->refcount;
    }

  *bdb_batonp = apr_palloc(pool, sizeof **bdb_batonp);
  (*bdb_batonp)->env = bdb->env;
  (*bdb_batonp)->bdb = bdb;
  (*bdb_batonp)->error_info = get_error_info(bdb);
  ++(*bdb_batonp)->error_info->refcount;
  apr_pool_cleanup_register(pool, *bdb_batonp, cleanup_env_baton,
                            apr_pool_cleanup_null);

  return SVN_NO_ERROR;
}
Example #3
0
int
main(int argc, char *argv[])
{
	time_t start;
	int ch, onerun, reps;
	const char *config, *home;

	config = NULL;

#ifdef _WIN32
	g.progname = "t_format.exe";
#else
	if ((g.progname = strrchr(argv[0], DIR_DELIM)) == NULL)
		g.progname = argv[0];
	else
		++g.progname;
#endif

#if 0
	/* Configure the GNU malloc for debugging. */
	(void)setenv("MALLOC_CHECK_", "2", 1);
#endif
#if 0
	/* Configure the FreeBSD malloc for debugging. */
	(void)setenv("MALLOC_OPTIONS", "AJ", 1);
#endif

	/* Track progress unless we're re-directing output to a file. */
	g.c_quiet = isatty(1) ? 0 : 1;

	/* Set values from the command line. */
	home = NULL;
	onerun = 0;
	while ((ch = __wt_getopt(
	    g.progname, argc, argv, "1C:c:H:h:Llqrt:")) != EOF)
		switch (ch) {
		case '1':			/* One run */
			onerun = 1;
			break;
		case 'C':			/* wiredtiger_open config */
			g.config_open = __wt_optarg;
			break;
		case 'c':			/* Configuration from a file */
			config = __wt_optarg;
			break;
		case 'H':
			g.helium_mount = __wt_optarg;
			break;
		case 'h':
			home = __wt_optarg;
			break;
		case 'L':			/* Re-direct output to a log */
			/*
			 * The -l option is a superset of -L, ignore -L if we
			 * have already configured logging for operations.
			 */
			if (g.logging == 0)
				g.logging = LOG_FILE;
			break;
		case 'l':			/* Turn on operation logging */
			g.logging = LOG_OPS;
			break;
		case 'q':			/* Quiet */
			g.c_quiet = 1;
			break;
		case 'r':			/* Replay a run */
			g.replay = 1;
			break;
		default:
			usage();
		}
	argc -= __wt_optind;
	argv += __wt_optind;

	/* Initialize the global RNG. */
	testutil_check(__wt_random_init_seed(NULL, &g.rnd));

	/* Set up paths. */
	path_setup(home);

	/* If it's a replay, use the home directory's CONFIG file. */
	if (g.replay) {
		if (config != NULL)
			testutil_die(EINVAL, "-c incompatible with -r");
		if (access(g.home_config, R_OK) != 0)
			testutil_die(ENOENT, "%s", g.home_config);
		config = g.home_config;
	}

	/*
	 * If we weren't given a configuration file, set values from "CONFIG",
	 * if it exists.
	 *
	 * Small hack to ignore any CONFIG file named ".", that just makes it
	 * possible to ignore any local CONFIG file, used when running checks.
	 */
	if (config == NULL && access("CONFIG", R_OK) == 0)
		config = "CONFIG";
	if (config != NULL && strcmp(config, ".") != 0)
		config_file(config);

	/*
	 * The rest of the arguments are individual configurations that modify
	 * the base configuration.
	 */
	for (; *argv != NULL; ++argv)
		config_single(*argv, 1);

	/*
	 * Multithreaded runs can be replayed: it's useful and we'll get the
	 * configuration correct.  Obviously the order of operations changes,
	 * warn the user.
	 */
	if (g.replay && !SINGLETHREADED)
		printf("Warning: replaying a threaded run\n");

	/*
	 * Single-threaded runs historically exited after a single replay, which
	 * makes sense when you're debugging, leave that semantic in place.
	 */
	if (g.replay && SINGLETHREADED)
		g.c_runs = 1;

	/*
	 * Let the command line -1 flag override runs configured from other
	 * sources.
	 */
	if (onerun)
		g.c_runs = 1;

	/*
	 * Initialize locks to single-thread named checkpoints and backups, last
	 * last-record updates, and failures.
	 */
	testutil_check(pthread_rwlock_init(&g.append_lock, NULL));
	testutil_check(pthread_rwlock_init(&g.backup_lock, NULL));
	testutil_check(pthread_rwlock_init(&g.checkpoint_lock, NULL));
	testutil_check(pthread_rwlock_init(&g.death_lock, NULL));

	printf("%s: process %" PRIdMAX "\n", g.progname, (intmax_t)getpid());
	while (++g.run_cnt <= g.c_runs || g.c_runs == 0 ) {
		startup();			/* Start a run */

		config_setup();			/* Run configuration */
		config_print(0);		/* Dump run configuration */
		key_len_setup();		/* Setup keys */

		start = time(NULL);
		track("starting up", 0ULL, NULL);

#ifdef HAVE_BERKELEY_DB
		if (SINGLETHREADED)
			bdb_open();		/* Initial file config */
#endif
		wts_open(g.home, true, &g.wts_conn);
		wts_init();

		wts_load();			/* Load initial records */
		wts_verify("post-bulk verify");	/* Verify */

		/*
		 * If we're not doing any operations, scan the bulk-load, copy
		 * the statistics and we're done. Otherwise, loop reading and
		 * operations, with a verify after each set.
		 */
		if (g.c_timer == 0 && g.c_ops == 0) {
			wts_read_scan();		/* Read scan */
			wts_stats();			/* Statistics */
		} else
			for (reps = 1; reps <= FORMAT_OPERATION_REPS; ++reps) {
				wts_read_scan();	/* Read scan */

							/* Operations */
				wts_ops(reps == FORMAT_OPERATION_REPS);

				/*
				 * Copy out the run's statistics after the last
				 * set of operations.
				 *
				 * XXX
				 * Verify closes the underlying handle and
				 * discards the statistics, read them first.
				 */
				if (reps == FORMAT_OPERATION_REPS)
					wts_stats();

							/* Verify */
				wts_verify("post-ops verify");
			}

		track("shutting down", 0ULL, NULL);
#ifdef HAVE_BERKELEY_DB
		if (SINGLETHREADED)
			bdb_close();
#endif
		wts_close();

		/*
		 * Rebalance testing.
		 */
		wts_rebalance();

		/*
		 * If single-threaded, we can dump and compare the WiredTiger
		 * and Berkeley DB data sets.
		 */
		if (SINGLETHREADED)
			wts_dump("standard", 1);

		/*
		 * Salvage testing.
		 */
		wts_salvage();

		/* Overwrite the progress line with a completion line. */
		if (!g.c_quiet)
			printf("\r%78s\r", " ");
		printf("%4d: %s, %s (%.0f seconds)\n",
		    g.run_cnt, g.c_data_source,
		    g.c_file_type, difftime(time(NULL), start));
		fflush(stdout);
	}

	/* Flush/close any logging information. */
	fclose_and_clear(&g.logfp);
	fclose_and_clear(&g.randfp);

	config_print(0);

	testutil_check(pthread_rwlock_destroy(&g.append_lock));
	testutil_check(pthread_rwlock_destroy(&g.backup_lock));
	testutil_check(pthread_rwlock_destroy(&g.checkpoint_lock));
	testutil_check(pthread_rwlock_destroy(&g.death_lock));

	config_clear();

	return (EXIT_SUCCESS);
}
Example #4
0
int
main(int argc, char *argv[])
{
	int ch, reps, ret;
	const char *config, *home;

	config = NULL;

	if ((g.progname = strrchr(argv[0], '/')) == NULL)
		g.progname = argv[0];
	else
		++g.progname;

#if 0
	/* Configure the GNU malloc for debugging. */
	(void)setenv("MALLOC_CHECK_", "2", 1);
#endif
#if 0
	/* Configure the FreeBSD malloc for debugging. */
	(void)setenv("MALLOC_OPTIONS", "AJ", 1);
#endif

	/* Track progress unless we're re-directing output to a file. */
	g.track = isatty(STDOUT_FILENO) ? 1 : 0;

	/* Set values from the command line. */
	home = NULL;
	while ((ch = getopt(argc, argv, "1C:c:h:Llqrt:")) != EOF)
		switch (ch) {
		case '1':			/* One run */
			g.c_runs = 1;
			break;
		case 'C':			/* wiredtiger_open config */
			g.config_open = optarg;
			break;
		case 'c':			/* Configuration from a file */
			config = optarg;
			break;
		case 'h':
			home = optarg;
			break;
		case 'L':			/* Re-direct output to a log */
			/*
			 * The -l option is a superset of -L, ignore -L if we
			 * have already configured logging for operations.
			 */
			if (g.logging == 0)
				g.logging = LOG_FILE;
			break;
		case 'l':			/* Turn on operation logging */
			g.logging = LOG_OPS;
			break;
		case 'q':			/* Quiet */
			g.track = 0;
			break;
		case 'r':			/* Replay a run */
			g.replay = 1;
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	/*
	 * If we weren't given a configuration file, set values from "CONFIG",
	 * if it exists.
	 *
	 * Small hack to ignore any CONFIG file named ".", that just makes it
	 * possible to ignore any local CONFIG file, used when running checks.
	 */
	if (config == NULL && access("CONFIG", R_OK) == 0)
		config = "CONFIG";
	if (config != NULL && strcmp(config, ".") != 0)
		config_file(config);

	/*
	 * The rest of the arguments are individual configurations that modify
	 * the base configuration.
	 */
	for (; *argv != NULL; ++argv)
		config_single(*argv, 1);

	/*
	 * Multithreaded runs can be replayed: it's useful and we'll get the
	 * configuration correct.  Obviously the order of operations changes,
	 * warn the user.
	 */
	if (g.replay && !SINGLETHREADED)
		printf("Warning: replaying a threaded run\n");

	/*
	 * Single-threaded runs historically exited after a single replay, which
	 * makes sense when you're debugging, leave that semantic in place.
	 */
	if (g.replay && SINGLETHREADED)
		g.c_runs = 1;

	/* Use line buffering on stdout so status updates aren't buffered. */
	(void)setvbuf(stdout, NULL, _IOLBF, 0);

	/*
	 * Initialize locks to single-thread named checkpoints and hot backups
	 * and to single-thread last-record updates.
	 */
	if ((ret = pthread_rwlock_init(&g.append_lock, NULL)) != 0)
		die(ret, "pthread_rwlock_init: append lock");
	if ((ret = pthread_rwlock_init(&g.backup_lock, NULL)) != 0)
		die(ret, "pthread_rwlock_init: hot-backup lock");

	/* Clean up on signal. */
	(void)signal(SIGINT, onint);

	/* Seed the random number generator. */
	srand((u_int)(0xdeadbeef ^ (u_int)time(NULL)));

	/* Set up paths. */
	path_setup(home);

	printf("%s: process %" PRIdMAX "\n", g.progname, (intmax_t)getpid());
	while (++g.run_cnt <= g.c_runs || g.c_runs == 0 ) {
		startup();			/* Start a run */

		config_setup();			/* Run configuration */
		config_print(0);		/* Dump run configuration */
		key_len_setup();		/* Setup keys */

		track("starting up", 0ULL, NULL);
		if (SINGLETHREADED)
			bdb_open();		/* Initial file config */
		wts_open(g.home, 1, &g.wts_conn);
		wts_create();

		wts_load();			/* Load initial records */
		wts_verify("post-bulk verify");	/* Verify */

						/* Loop reading & operations */
		for (reps = 0; reps < 3; ++reps) {
			wts_read_scan();	/* Read scan */

			if (g.c_ops != 0)	/* Random operations */
				wts_ops();

			/*
			 * Statistics.
			 *
			 * XXX
			 * Verify closes the underlying handle and discards the
			 * statistics, read them first.
			 */
			if (g.c_ops == 0 || reps == 2)
				wts_stats();

						/* Verify */
			wts_verify("post-ops verify");

			/*
			 * If no operations scheduled, quit after a single
			 * read pass.
			 */
			if (g.c_ops == 0)
				break;
		}

		track("shutting down", 0ULL, NULL);
		if (SINGLETHREADED)
			bdb_close();
		wts_close();

		/*
		 * If single-threaded, we can dump and compare the WiredTiger
		 * and Berkeley DB data sets.
		 */
		if (SINGLETHREADED)
			wts_dump("standard", 1);

		/*
		 * If no records are deleted, we can salvage the file and test
		 * the result.  (The problem with deleting records is salvage
		 * restores deleted records if a page splits leaving a deleted
		 * record on one side of the split.)
		 *
		 * Salvage, verify the salvaged files, then dump (comparing
		 * against the Berkeley DB data set again, if possible).
		 */
		if (g.c_delete_pct == 0) {
			wts_open(g.home, 1, &g.wts_conn);
			wts_salvage();
			wts_verify("post-salvage verify");
			wts_close();

			wts_dump("salvage", SINGLETHREADED);
		}

		/* Overwrite the progress line with a completion line. */
		if (g.track)
			printf("\r%78s\r", " ");
		printf("%4d: %s, %s\n",
		    g.run_cnt, g.c_data_source, g.c_file_type);
	}

	/* Flush/close any logging information. */
	if (g.logfp != NULL)
		(void)fclose(g.logfp);
	if (g.rand_log != NULL)
		(void)fclose(g.rand_log);

	config_print(0);

	if ((ret = pthread_rwlock_destroy(&g.append_lock)) != 0)
		die(ret, "pthread_rwlock_destroy: append lock");
	if ((ret = pthread_rwlock_destroy(&g.backup_lock)) != 0)
		die(ret, "pthread_rwlock_destroy: hot-backup lock");

	config_clear();

	return (EXIT_SUCCESS);
}