new_contents: """
  CacheItem interface:
  'url': string,
  'response_url': string,
  'body': string,
  'head': string,
  'response_code': int,
  'cookies': None,#grab.response.cookies,
  
  TODO: WTF with cookies???
  """
  from __future__ import absolute_import
  import tc
  import os
  import logging
  import marshal
  
  from grab.response import Response
  
  logger = logging.getLogger('grab.spider.cache_backend.mongo')
  
  
  class CacheBackend(object):
      def __init__(self, database, use_compression=True):
          # database == filename
          self.db = tc_open(database, compress=use_compression)
          self.use_compression = use_compression
  
      def get_item(self, url):
          """
          Returned item should have specific interface. See module docstring.
          """
          try:
              dump = self.db[self.build_key(url)]
          except KeyError:
              return
          return marshal.loads(dump)
  
      def build_key(self, url):
          return url.encode('utf-8') if isinstance(url, unicode) else url
  
      def remove_cache_item(self, url):
          del self.db[self.build_key(url)]
  
      def load_response(self, grab, cache_item):
          grab.fake_response(cache_item['body'])
          body = cache_item['body']
  
          def custom_prepare_response_func(transport, g):
              response = Response()
              response.head = cache_item['head']
              response.body = body
              response.code = cache_item['response_code']
              response.time = 0
  
              # Hack for deprecated behaviour
              if 'response_url' in cache_item:
                  response.url = cache_item['response_url']
              else:
                  logger.debug('You cache contains items without `response_url` key. It is depricated data format. Please re-download you cache or build manually `response_url` keys.')
                  response.url = cache_item['url']
  
              response.parse()
              response.cookies = transport.extract_cookies()
              return response
  
          grab.process_request_result(custom_prepare_response_func)
  
      def save_response(self, url, grab):
          body = grab.response.body
          item = {
              'url': url,
              'response_url': grab.response.url,
              'body': body,
              'head': grab.response.head,
              'response_code': grab.response.code,
              'cookies': None,
          }
          self.db[self.build_key(url)] = marshal.dumps(item)
  
  def tc_open(path, mode='a+', compress=True, makedirs=True):
      if makedirs:
          try:
              os.makedirs(os.path.dirname(path))
          except OSError:
              pass
  
      db = tc.HDB()
      if compress:
          db.tune(-1, -1, -1, tc.HDBTDEFLATE)
      db.open(path,
          {
              'r': tc.HDBOREADER,
              'w': tc.HDBOWRITER | tc.HDBOCREAT | tc.HDBOTRUNC,
              'a': tc.HDBOWRITER,
              'a+': tc.HDBOWRITER | tc.HDBOCREAT,
          }[mode]
      )
      return db
  
  
subject: Add tokyo cabinet cache backend