@gen.engine
  def SelectCoverPhoto(self, client, exclude_posts_set, callback, activities_list=None, available_posts_dict=None):
    from viewfinder.backend.db.post import Post
    batch_limit = 50

    # cover_photo is not supported on default viewpoints.
    assert not self.IsDefault(), self

    @gen.coroutine
    def _QueryAvailablePost(episode_id, photo_id):
      if available_posts_dict is not None:
        post = available_posts_dict.get(Post.ConstructPostId(episode_id, photo_id), None)
      else:
        post = yield gen.Task(Post.Query, client, episode_id, photo_id, col_names=None)
        if post.IsRemoved():
          post = None
      raise gen.Return(post)

    # Loop over activities starting from the oldest.
    excl_start_key = None
    while True:
      if activities_list is None:
        activities = yield gen.Task(Activity.RangeQuery,
                                    client,
                                    self.viewpoint_id,
                                    range_desc=None,
                                    limit=batch_limit,
                                    col_names=None,
                                    excl_start_key=excl_start_key,
                                    scan_forward=False)
      else:
        activities = activities_list

      for activity in activities:
        if activity.name == 'share_new' or activity.name == 'share_existing':
          args_dict = json.loads(activity.json)
          # Now, loop through the episodes in the activity.
          for ep_dict in args_dict['episodes']:
            episode_id = ep_dict['episode_id']
            # And loop through the photos in each episode.
            for photo_id in ep_dict['photo_ids']:
              # Save cost of query on a post that we know is UNSHARED.
              if (episode_id, photo_id) not in exclude_posts_set:
                post = yield _QueryAvailablePost(episode_id, photo_id)
                if post is not None:
                  # If it hasn't been unshared, we're good to go.
                  callback(Viewpoint.ConstructCoverPhoto(episode_id, photo_id))
                  return

      if activities_list is not None or len(activities) < batch_limit:
        break
      else:
        excl_start_key = activities[-1].GetKey()

    # No unshared photos found in this viewpoint.
    callback(None)
Determine whether the current volume state of an application is
dataset/ETHPy150Open viewfinderco/viewfinder/backend/db/viewpoint.py/Viewpoint.SelectCoverPhoto--crossover with--dataset/ETHPy150Open ClusterHQ/flocker/flocker/node/_container.py/ApplicationNodeDeployer._restart_for_volume_change