def push(self, task):
        """
            Extract new updates from the local database and send
            them to the peer repository (active push)

            @param task: the synchronization task (sync_task Row)

            @return: tuple (error, mtime), with error=None if successful,
                     else error=message, and mtime=modification timestamp
                     of the youngest record sent
        """

        repository = self.repository
        resource_name = task.resource_name
        log = repository.log
        remote = False
        output = None

        current.log.debug("S3SyncRepository.push(%s, %s)" % (repository.url,
                                                             resource_name))

        # Define the resource
        resource = current.s3db.resource(resource_name,
                                         # FTP remote deletion is not supported yet
                                         #include_deleted=True,
                                         )

        # Apply sync filters for this task
        filters = current.sync.get_filters(task.id)
        table = resource.table
        tablename = resource.tablename

        if filters:
            queries = S3URLQuery.parse(resource, filters[tablename])
            [resource.add_filter(q) for a in queries for q in queries[a]]

        # Filter to records after last push
        msince = task.last_push

        if msince:
            strategy = task.strategy
            created = "create" in strategy
            updated = "update" in strategy
            if created and updated:
                mtime_filter = table.modified_on > msince
            elif created:
                mtime_filter = table.created_on > msince
            elif updated:
                mtime_filter = (table.created_on <= msince) & \
                               (table.modified_on > msince)
            else:
                mtime_filter = None

            if mtime_filter:
                resource.add_filter(mtime_filter)

        mtime = resource.muntil
        # Get the ID of the resource after filter and msince
        resource_ids = resource.get_id()

        # No Changes since last push?
        if resource_ids is None:
            message = "No Changes since last push"
            result = log.WARNING
        else:
            # Filename
            settings = current.deployment_settings
            # Placeholders for filename
            placeholders = {"systemname": settings.get_system_name(),
                            "systemname_short": settings.get_system_name_short(),
                            "resource": resource_name,
                            "public_url": settings.get_base_public_url(),
                            }

            from string import Template
            filename = resource.get_config("upload_filename")
            if not filename:
                filename = settings.get_sync_upload_filename()
            filename = Template(filename).safe_substitute(s="%(systemname_short)s",
                                                          r="%(resource)s")
            filename = filename % placeholders
            # Get Representation
            representation = task.representation
            filename = ("%s.%s") % (filename, representation)

            # FTP Transfer
            remote = True
            import ftplib
            ftp_connection = self.ftp_connection
            if task.multiple_file:
                if type(resource_ids) is not list:
                    resource_ids = [resource_ids]

                for resource_id in resource_ids:
                    resource.clear_query()
                    resource.add_filter(FS("id") == resource_id)
                    data = self._get_data(resource, representation)

                    try:
                        ftp_connection.storbinary("STOR %s" % filename,
                                                  StringIO(data))
                    except ftplib.error_perm:
                        message = sys.exc_info()[1]
                        result = log.ERROR
                        output = message
                    else:
                        message = "FTP Transfer Successful"
                        result = log.SUCCESS

                    current.log.debug(message)
            else:
                data = self._get_data(resource, representation)

                try:
                    ftp_connection.storbinary("STOR %s" % filename,
                                              StringIO(data))
                except ftplib.error_perm:
                    message = sys.exc_info()[1]
                    result = log.ERROR
                    output = message
                else:
                    message = "FTP Transfer Successful"
                    result = log.SUCCESS

                current.log.debug(message)

            # Quit the connection here
            ftp_connection.quit()

        # Log the operation
        log.write(repository_id = repository.id,
                  resource_name = resource_name,
                  transmission = log.OUT,
                  mode = log.PUSH,
                  action = "send",
                  remote = remote,
                  result = result,
                  message = message,
                  )
        # Returns after operation is complete
        if output is not None:
            mtime = None
        return output, mtime

    # -------------------------------------------------------------------------
    # Internal methods:
    # -------------------------------------------------------------------------
dataset/ETHPy150Open sahana/eden/modules/s3/sync_adapter/ftp.py/S3SyncAdapter.push/original