Parse and update from archived cache files. Only accept new content;
        do not overwrite any existing cache content.

        :param base_dir: archive base directory
        :param timestamp: epoch time of cache serving as subdirectory, default most recent
        :return: epoch time of cache serving as subdirectory, None if there is no such archive.

def parse(base_dir: str, timestamp: int = None) -> int:
        """
        Parse and update from archived cache files. Only accept new content;
        do not overwrite any existing cache content.

        :param base_dir: archive base directory
        :param timestamp: epoch time of cache serving as subdirectory, default most recent
        :return: epoch time of cache serving as subdirectory, None if there is no such archive.
        """

        LOGGER.debug('parse >>> base_dir: %s, timestamp: %s', base_dir, timestamp)

        if not isdir(base_dir):
            LOGGER.info('No cache archives available: not feeding cache')
            LOGGER.debug('parse <<< None')
            return None

        if not timestamp:
            timestamps = [int(t) for t in listdir(base_dir) if t.isdigit()]
            if timestamps:
                timestamp = max(timestamps)
            else:
                LOGGER.info('No cache archives available: not feeding cache')
                LOGGER.debug('parse <<< None')
                return None

        timestamp_dir = join(base_dir, str(timestamp))
        if not isdir(timestamp_dir):
            LOGGER.error('No such archived cache directory: %s', timestamp_dir)
            LOGGER.debug('parse <<< None')
            return None

        with SCHEMA_CACHE.lock:
            with open(join(timestamp_dir, 'schema'), 'r') as archive:
                schemata = json.loads(archive.read())
                SCHEMA_CACHE.feed(schemata)

        with CRED_DEF_CACHE.lock:
            with open(join(timestamp_dir, 'cred_def'), 'r') as archive:
                cred_defs = json.loads(archive.read())
                for cd_id in cred_defs:
                    if cd_id in CRED_DEF_CACHE:
                        LOGGER.warning('Cred def cache already has cred def on %s: skipping', cd_id)
                    else:
                        CRED_DEF_CACHE[cd_id] = cred_defs[cd_id]
                        LOGGER.info('Cred def cache imported cred def for cred def id %s', cd_id)

        with REVO_CACHE.lock:
            with open(join(timestamp_dir, 'revocation'), 'r') as archive:
                rr_cache_entries = json.loads(archive.read())
                for (rr_id, entry) in rr_cache_entries.items():
                    if rr_id in REVO_CACHE:
                        LOGGER.warning('Revocation cache already has entry on %s: skipping', rr_id)
                    else:
                        rr_cache_entry = RevoCacheEntry(entry['rev_reg_def'])

                        rr_cache_entry.rr_delta_frames = [
                            RevRegUpdateFrame(
                                f['_to'],
                                f['_timestamp'],
                                f['_rr_update']) for f in entry['rr_delta_frames']
                        ]
                        rr_cache_entry.cull(True)

                        rr_cache_entry.rr_state_frames = [
                            RevRegUpdateFrame(
                                f['_to'],
                                f['_timestamp'],
                                f['_rr_update']) for f in entry['rr_state_frames']
                        ]
                        rr_cache_entry.cull(False)

                        REVO_CACHE[rr_id] = rr_cache_entry
                        LOGGER.info('Revocation cache imported entry for rev reg id %s', rr_id)

        LOGGER.debug('parse <<< %s', timestamp)
        return timestamp