Clone

	Clone is used to clone one or many DBs/Tables from one host to another

	Args:
		source (dict): Data specifying the source instance
			A dictionary with the following possible elements: host, port, user,
			password, timeout, ssl (see rethinkdb python api)

		destination (dict): Date specifying the destination instance
			Works the same as source, but for the destination host

		dbs (list|dict): A list of DBs
			This is the list of Databases that will be cloned. If the value is a
			list, all tables in each DB with be cloned. If the value is a dict,
			it is assumed the keys are the names of the DBs, and the value (a
			list) is the tables that will be cloned from each DB

		verbose (bool): Optional verbose flag
			If true the function will print out details about what it's doing.
			Defaults to False

	Returns:
		bool: Returns true on success

	Raises:
		ValueError: If any arguments are incorrect a ValueError will be raised

def clone(source, destination, dbs = None, verbose = False):
	"""Clone

	Clone is used to clone one or many DBs/Tables from one host to another

	Args:
		source (dict): Data specifying the source instance
			A dictionary with the following possible elements: host, port, user,
			password, timeout, ssl (see rethinkdb python api)

		destination (dict): Date specifying the destination instance
			Works the same as source, but for the destination host

		dbs (list|dict): A list of DBs
			This is the list of Databases that will be cloned. If the value is a
			list, all tables in each DB with be cloned. If the value is a dict,
			it is assumed the keys are the names of the DBs, and the value (a
			list) is the tables that will be cloned from each DB

		verbose (bool): Optional verbose flag
			If true the function will print out details about what it's doing.
			Defaults to False

	Returns:
		bool: Returns true on success

	Raises:
		ValueError: If any arguments are incorrect a ValueError will be raised
	"""

	# If the source is not a valid dict
	if not isinstance(source, dict):
		raise ValueError('source must be a dict')

	# Open a connection to the source instance
	try:
		oSource	= r.connect(**source)

	# Catch possible error
	except r.errors.RqlDriverError:
		sys.stderr.write('Can not connect to source host: ' + str(source) + '\n')
		return False

	# If the destination is not a valid dict
	if not isinstance(destination, dict):
		raise ValueError('destination must be a dict')

	# Open a connection to the destination instance
	try:
		oDest	= r.connect(**destination)

	# Catch possible error
	except r.errors.RqlDriverError:
		sys.stderr.write('Can not connect to destination host: ' + str(destination) + '\n')
		return False

	# Get all the DBs on the source
	lSourceDBs	= r.db_list().run(oSource)

	# If no DBs were specified
	if not dbs:
		dbs	= lSourceDBs

	# If the DBs were sent as a list (no tables specified)
	if isinstance(dbs, (list,tuple)):
		dbs	= {s:None for s in dbs}

	# Go through each DB listed
	for sDB,lTables in dbs.iteritems():

		# DBs can't have spaces, so we assume we want to rename the DB if there is one
		if ' ' in sDB:
			sDB, sCopyDB = sDB.split(' ')
		else:
			sCopyDB = sDB

		# If the DB doesn't exist in the source
		if sDB not in lSourceDBs:
			sys.stderr.write('No such DB "%s" on the source host\n' % sDB)
			continue

		# Check if the DB exists on the destination
		if r.db_list().contains(sCopyDB).run(oDest):
			sys.stderr.write('DB "%s" already exists on the destination host\n"' % sDB)
			continue

		# If verbose mode is on
		if verbose:
			sys.stdout.write('Processing DB "%s"\n' % sDB)

		# Create the DB on the destination host
		r.db_create(sCopyDB).run(oDest)

		# Get all the tables in the DB
		lSourceTables	= r.db(sDB).table_list().run(oSource)

		# If no tables were specified
		if not lTables:
			lTables	= lSourceTables

		# Go through each Table
		for sTable in lTables:

			# If the DB doesn't exist in the source
			if sTable not in lSourceTables:
				sys.stderr.write('No such Table "%s.%s" on the source host\n' % (sDB,sTable))
				continue

			# If verbose mode is on
			if verbose:

				# Output
				sys.stdout.write('  Processing Table "%s": [%s] 0%%' % (sTable, (' ' * _PROGRESS_TICKS)))

				# Get the number of documents in the table
				fTotal	= float(r.db(sDB).table(sTable).count().run(oSource))

				# Calculate the block size
				fBlock	= fTotal / _PROGRESS_TICKS

				# Init the count and the ticks
				iCount	= 0
				iTicks	= 0

			# Get the primary key of the table
			sKeyField	= r.db(sDB).table(sTable).info().run(oSource)['primary_key']

			# Create the Table
			r.db(sCopyDB).table_create(sTable, primary_key=sKeyField).run(oDest)

			# Get the list of indexes
			lIndexes	= r.db(sDB).table(sTable).index_status().run(oSource)

			# Create each index
			for dIndex in lIndexes:

				# Pull out the name
				sName	= dIndex['index']

				# Pull out the fields
				oMatches	= _INDEX_REGEX.findall(dIndex['query'])

				# If there's only one field
				if len(oMatches) == 1:

					# Create a single field index
					r.db(sCopyDB).table(sTable).index_create(oMatches[0][0]).run(oDest)

				# Else if the index is comprised of multiple fields
				else:

					# Pull out each field
					lFields	= []
					for tMatch in oMatches:
						lFields.append(r.row[tMatch[1]])

					# Create a multi-index field
					r.db(sCopyDB).table(sTable).index_create(sName, lFields).run(oDest)

			# Copy the data one document at a time
			for dDoc in r.db(sDB).table(sTable).run(oSource):

				# Copy the document to the destination
				r.db(sCopyDB).table(sTable).insert(dDoc).run(oDest)

				# If verbose mode is on
				if verbose:

					# Increment the count
					iCount	+= 1

					# Get the number of ticks
					iTemp	= int(round(float(iCount) / fBlock))

					# If the ticks are more than the previous
					if iTemp > iTicks:
						iTicks	= iTemp

						# Output
						sys.stdout.write('\r  Processing Table "%s": [%s%s] %d%%' % (
							sTable,
							('=' * iTicks),
							(' ' * (_PROGRESS_TICKS - iTicks)),
							(iTicks * 4)
						))
						sys.stdout.flush()

			# If verbose mode is on
			if verbose:

				# Output
				sys.stdout.write('\r  Processing Table "%s": [%s] 100%%\n' % (sTable, ('=' * _PROGRESS_TICKS)))