<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 async def _send_rev_reg_def(self, rr_id: str) -> None: """ Move tails file from hopper; deserialize revocation registry definition and initial entry; send to ledger and cache revocation registry definition. Operation serializes to subdirectory within tails hopper directory; symbolic link presence signals completion. Raise AbsentRevReg if revocation registry is not ready in hopper, or AbsentTails if tails file is not yet linked by its revocation registry identifier. :param rr_id: revocation registry identifier """


        LOGGER.debug('Issuer._send_rev_reg_def >>> rr_id: %s', rr_id)

        dir_tails_rr_id = self.rrb.dir_tails_top(rr_id)
        dir_target = self.rrb.dir_tails_target(rr_id)

        if not Tails.linked(dir_tails_rr_id, rr_id):
            LOGGER.debug(
                'Issuer._send_rev_reg_def <!< Tails file for rev reg %s not ready in dir %s',
                rr_id,
                dir_target)
            raise AbsentRevReg('Tails file for rev reg {} not ready in dir {}'.format(rr_id, dir_target))

        file_rr_def = join(dir_target, 'rr_def.json')
        if not isfile(file_rr_def):
            LOGGER.debug('Issuer._send_rev_reg_def <!< Rev reg def file %s not present', file_rr_def)
            raise AbsentRevReg('Rev reg def file {} not present'.format(file_rr_def))
        with open(file_rr_def, 'r') as fh_rr_def:
            rr_def_json = fh_rr_def.read()

        file_rr_ent = join(dir_target, 'rr_ent.json')
        if not isfile(file_rr_ent):
            LOGGER.debug('Issuer._send_rev_reg_def <!< Rev reg entry file %s not present', file_rr_ent)
            raise AbsentRevReg('Rev reg entry file {} not present'.format(file_rr_ent))
        with open(file_rr_ent, 'r') as fh_rr_ent:
            rr_ent_json = fh_rr_ent.read()

        file_tails = Tails.linked(dir_tails_rr_id, rr_id)
        if not file_tails:
            LOGGER.debug('Issuer._send_rev_reg_def <!< Tails link %s not present in dir %s', rr_id, dir_target)
            raise AbsentTails('Tails link {} not present in dir {}'.format(rr_id, dir_target))

        if self.rrbx:
            dir_cd_id = join(self.dir_tails, rev_reg_id2cred_def_id(rr_id))
            makedirs(dir_cd_id, exist_ok=True)
            rename(file_tails, join(dir_cd_id, basename(file_tails)))

        with REVO_CACHE.lock:
            rr_def_req_json = await ledger.build_revoc_reg_def_request(self.did, rr_def_json)
            await self._sign_submit(rr_def_req_json)
            await self.get_rev_reg_def(rr_id)  # add to cache en passant

        rr_ent_req_json = await ledger.build_revoc_reg_entry_request(self.did, rr_id, 'CL_ACCUM', rr_ent_json)
        await self._sign_submit(rr_ent_req_json)

        if self.rrbx:
            Tails.associate(self.dir_tails, rr_id, basename(file_tails))
            rmtree(dir_tails_rr_id)
        else:
            remove(file_rr_def)
            remove(file_rr_ent)

        LOGGER.debug('Issuer._send_rev_reg_def <<<')