def database_backup(self, data_directory, *args, **kwargs):
upload_good = False<EOL>backup_stop_good = False<EOL>while_offline = False<EOL>start_backup_info = None<EOL>if '<STR_LIT>' in kwargs:<EOL><INDENT>while_offline = kwargs.pop('<STR_LIT>')<EOL><DEDENT>try:<EOL><INDENT>if not while_offline:<EOL><INDENT>start_backup_info = PgBackupStatements.run_start_backup()<EOL>version = PgBackupStatements.pg_version()['<STR_LIT:version>']<EOL><DEDENT>else:<EOL><INDENT>if os.path.exists(os.path.join(data_directory,<EOL>'<STR_LIT>')):<EOL><INDENT>hint = ('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL>raise UserException(<EOL>msg='<STR_LIT>',<EOL>detail='<STR_LIT>',<EOL>hint=hint)<EOL><DEDENT>ctrl_data = PgControlDataParser(data_directory)<EOL>start_backup_info = ctrl_data.last_xlog_file_name_and_offset()<EOL>version = ctrl_data.pg_version()<EOL><DEDENT>ret_tuple = self._upload_pg_cluster_dir(<EOL>start_backup_info, data_directory, version=version, *args,<EOL>**kwargs)<EOL>spec, uploaded_to, expanded_size_bytes = ret_tuple<EOL>upload_good = True<EOL><DEDENT>finally:<EOL><INDENT>if not upload_good:<EOL><INDENT>logger.warning(<EOL>'<STR_LIT>',<EOL>detail=('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'))<EOL><DEDENT>if not while_offline:<EOL><INDENT>stop_backup_info = PgBackupStatements.run_stop_backup()<EOL><DEDENT>else:<EOL><INDENT>stop_backup_info = start_backup_info<EOL><DEDENT>backup_stop_good = True<EOL><DEDENT>if upload_good and backup_stop_good:<EOL><INDENT>sentinel_content = json.dumps(<EOL>{'<STR_LIT>':<EOL>stop_backup_info['<STR_LIT>'],<EOL>'<STR_LIT>':<EOL>stop_backup_info['<STR_LIT>'],<EOL>'<STR_LIT>': expanded_size_bytes,<EOL>'<STR_LIT>': spec})<EOL>uri_put_file(self.creds,<EOL>uploaded_to + '<STR_LIT>',<EOL>BytesIO(sentinel_content.encode("<STR_LIT:utf8>")),<EOL>content_type='<STR_LIT:application/json>')<EOL><DEDENT>else:<EOL><INDENT>raise UserCritical('<STR_LIT>')<EOL><DEDENT>
Uploads a PostgreSQL file cluster to S3 or Windows Azure Blob
        Service

        Mechanism: just wraps _upload_pg_cluster_dir with
        start/stop backup actions with exception handling.

        In particular there is a 'finally' block to stop the backup in
        most situations.