docs: def cleanup(self, ctime=None):
          '''
          This method is called iteratively by the connection owning it.
          Its job is to control the size of cache and remove old entries.
          '''
          ctime = ctime or time.time()
          if self.last_cleanup:
              self.average_cleanup_time.add_point(ctime - self.last_cleanup)
          self.last_cleanup = ctime
  
          log.debug('couchdb', "Running cache cleanup().")
          # first remove already invalidated entries, used this iteration to
          # build up the map of usage
          expire = list()
  
          # [(num_accessed / time_in_cache, size, ident)]
          usage = list()
  
          actual_size = 0
  
          for ident, entry in self.iteritems():
              if entry.state is EntryState.invalid:
                  expire.append(ident)
                  continue
              elif entry.state is EntryState.waiting:
                  continue
              else: # EntryState.ready
                  actual_size += entry.size
                  time_in_cache = max([ctime - entry.cached_at, 1])
                  usage.append((
                      float(entry.num_accessed) / time_in_cache,
                      -entry.size,
                      ident))
  
          self.average_size.add_point(actual_size)
  
          if self.average_size.get_value() > 3 * self.desired_size:
              log.warning("couchdb", "The average size of Cache is %.2f times "
                          "bigger than the desired size of: %s. It might be "
                          "a good idea to rethink the caching strategy.",
                          self.average_size.get_value() / self.desired_size,
                          self.desired_size)
  
          if actual_size > self.desired_size:
              log.debug('couchdb', "I will have to cleanup some data, "
                        "the actual size is: %s, the desired limit is %s.",
                        actual_size, self.desired_size)
              # The usage list is sorted in order of things I will
              # be removing first. The important factor is "density" of usages
              # in time.
              usage.sort()
              size_to_delete = 0
              num_to_delete = 0
              while (len(usage) > 1 and
                     actual_size - size_to_delete > self.desired_size):
                  _, negative_size, ident = usage.pop(0)
                  size_to_delete += -negative_size
                  num_to_delete += 1
                  expire.append(ident)
              log.debug('couchdb', "I will remove %d entries from cache of the "
                        "size of %s to compensate the size.",
                        num_to_delete, size_to_delete)
  
          for ident in expire:
              del self[ident]