<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0):
        '''
        Sets multiple keys in the memcache doing just one query.

        >>> notset_keys = mc.set_multi({'key1' : 'val1', 'key2' : 'val2'})
        >>> mc.get_multi(['key1', 'key2']) == {'key1' : 'val1', 'key2' : 'val2'}
        1


        This method is recommended over regular L{set} as it lowers the
        number of total packets flying around your network, reducing
        total latency, since your app doesn't have to wait for each
        round-trip of L{set} before sending the next one.

        @param mapping: A dict of key/value pairs to set.
        @param time: Tells memcached the time which this value should
            expire, either as a delta number of seconds, or an absolute
            unix time-since-the-epoch value. See the memcached protocol
            docs section "Storage Commands" for more info on <exptime>. We
            default to 0 == cache forever.
        @param key_prefix:  Optional string to prepend to each key when
            sending to memcache. Allows you to efficiently stuff these
            keys into a pseudo-namespace in memcache:

            >>> notset_keys = mc.set_multi(
            ...     {'key1' : 'val1', 'key2' : 'val2'}, key_prefix='subspace_')
            >>> len(notset_keys) == 0
            True
            >>> mc.get_multi(['subspace_key1', 'subspace_key2']) == {'subspace_key1' : 'val1', 'subspace_key2' : 'val2'}
            True

            Causes key 'subspace_key1' and 'subspace_key2' to be
            set. Useful in conjunction with a higher-level layer which
            applies namespaces to data in memcache.  In this case, the
            return result would be the list of notset original keys,
            prefix not applied.

        @param min_compress_len: The threshold length to kick in
            auto-compression of the value using the zlib.compress()
            routine. If the value being cached is a string, then
            the length of the string is measured, else if the value
            is an object, then the length of the pickle result is
            measured. If the resulting attempt at compression yeilds
            a larger string than the input, then it is discarded. For
            backwards compatability, this parameter defaults to 0,
            indicating don't ever try to compress.
        @return: List of keys which failed to be stored [ memcache out of
           memory, etc. ].
        @rtype: list

        '''

        self._statlog('set_multi')

        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(
                mapping.iterkeys(), key_prefix)

        # send out all requests on each server before reading anything
        dead_servers = []
        notstored = [] # original keys.

        for server in server_keys.iterkeys():
            bigcmd = []
            write = bigcmd.append
            try:
                for key in server_keys[server]: # These are mangled keys
                    store_info = self._val_to_store_info(
                            mapping[prefixed_to_orig_key[key]],
                            min_compress_len)
                    if store_info:
                        write("set %s %d %d %d\r\n%s\r\n" % (key, store_info[0],
                                time, store_info[1], store_info[2]))
                    else:
                        notstored.append(prefixed_to_orig_key[key])
                server.send_cmds(''.join(bigcmd))
            except socket.error, msg:
                if isinstance(msg, tuple): msg = msg[1]
                server.mark_dead(msg)
                dead_servers.append(server)

        # if any servers died on the way, don't expect them to respond.
        for server in dead_servers:
            del server_keys[server]

        #  short-circuit if there are no servers, just return all keys
        if not server_keys: return(mapping.keys())

        for server, keys in server_keys.iteritems():
            try:
                for key in keys:
                    if server.readline() == 'STORED':
                        continue
                    else:
                        notstored.append(prefixed_to_orig_key[key]) #un-mangle.
            except (_Error, socket.error), msg:
                if isinstance(msg, tuple): msg = msg[1]
                server.mark_dead(msg)
        return notstored