468 delete_item = request.add_item() |
468 delete_item = request.add_item() |
469 delete_item.set_key(_key_string(key)) |
469 delete_item.set_key(_key_string(key)) |
470 delete_item.set_delete_time(int(math.ceil(seconds))) |
470 delete_item.set_delete_time(int(math.ceil(seconds))) |
471 try: |
471 try: |
472 self._make_sync_call('memcache', 'Delete', request, response) |
472 self._make_sync_call('memcache', 'Delete', request, response) |
473 except apiproxy_errors.ApplicationError: |
473 except apiproxy_errors.Error: |
474 return DELETE_NETWORK_FAILURE |
474 return DELETE_NETWORK_FAILURE |
475 assert response.delete_status_size() == 1, 'Unexpected status size.' |
475 assert response.delete_status_size() == 1, 'Unexpected status size.' |
476 |
476 |
477 if response.delete_status(0) == MemcacheDeleteResponse.DELETED: |
477 if response.delete_status(0) == MemcacheDeleteResponse.DELETED: |
478 return DELETE_SUCCESSFUL |
478 return DELETE_SUCCESSFUL |
510 delete_item = request.add_item() |
510 delete_item = request.add_item() |
511 delete_item.set_key(_key_string(key, key_prefix=key_prefix)) |
511 delete_item.set_key(_key_string(key, key_prefix=key_prefix)) |
512 delete_item.set_delete_time(int(math.ceil(seconds))) |
512 delete_item.set_delete_time(int(math.ceil(seconds))) |
513 try: |
513 try: |
514 self._make_sync_call('memcache', 'Delete', request, response) |
514 self._make_sync_call('memcache', 'Delete', request, response) |
515 except apiproxy_errors.ApplicationError: |
515 except apiproxy_errors.Error: |
516 return False |
516 return False |
517 return True |
517 return True |
518 |
518 |
519 def set(self, key, value, time=0, min_compress_len=0): |
519 def set(self, key, value, time=0, min_compress_len=0): |
520 """Sets a key's value, regardless of previous contents in cache. |
520 """Sets a key's value, regardless of previous contents in cache. |
605 item.set_set_policy(policy) |
605 item.set_set_policy(policy) |
606 item.set_expiration_time(int(math.ceil(time))) |
606 item.set_expiration_time(int(math.ceil(time))) |
607 response = MemcacheSetResponse() |
607 response = MemcacheSetResponse() |
608 try: |
608 try: |
609 self._make_sync_call('memcache', 'Set', request, response) |
609 self._make_sync_call('memcache', 'Set', request, response) |
610 except apiproxy_errors.ApplicationError: |
610 except apiproxy_errors.Error: |
611 return False |
611 return False |
612 if response.set_status_size() != 1: |
612 if response.set_status_size() != 1: |
613 return False |
613 return False |
614 return response.set_status(0) == MemcacheSetResponse.STORED |
614 return response.set_status(0) == MemcacheSetResponse.STORED |
615 |
615 |
|
616 def _set_multi_with_policy(self, policy, mapping, time=0, key_prefix=''): |
|
617 """Set multiple keys with a specified policy. |
|
618 |
|
619 Helper function for set_multi(), add_multi(), and replace_multi(). This |
|
620 reduces the network latency of doing many requests in serial. |
|
621 |
|
622 Args: |
|
623 policy: One of MemcacheSetRequest.SET, ADD, or REPLACE. |
|
624 mapping: Dictionary of keys to values. |
|
625 time: Optional expiration time, either relative number of seconds |
|
626 from current time (up to 1 month), or an absolute Unix epoch time. |
|
627 By default, items never expire, though items may be evicted due to |
|
628 memory pressure. Float values will be rounded up to the nearest |
|
629 whole second. |
|
630 key_prefix: Prefix for to prepend to all keys. |
|
631 |
|
632 Returns: |
|
633 A list of keys whose values were NOT set. On total success, |
|
634 this list should be empty. On network/RPC/server errors, |
|
635 a list of all input keys is returned; in this case the keys |
|
636 may or may not have been updated. |
|
637 """ |
|
638 if not isinstance(time, (int, long, float)): |
|
639 raise TypeError('Expiration must be a number.') |
|
640 if time < 0.0: |
|
641 raise ValueError('Expiration must not be negative.') |
|
642 |
|
643 request = MemcacheSetRequest() |
|
644 user_key = {} |
|
645 server_keys = [] |
|
646 for key, value in mapping.iteritems(): |
|
647 server_key = _key_string(key, key_prefix, user_key) |
|
648 stored_value, flags = _validate_encode_value(value, self._do_pickle) |
|
649 server_keys.append(server_key) |
|
650 |
|
651 item = request.add_item() |
|
652 item.set_key(server_key) |
|
653 item.set_value(stored_value) |
|
654 item.set_flags(flags) |
|
655 item.set_set_policy(policy) |
|
656 item.set_expiration_time(int(math.ceil(time))) |
|
657 |
|
658 response = MemcacheSetResponse() |
|
659 try: |
|
660 self._make_sync_call('memcache', 'Set', request, response) |
|
661 except apiproxy_errors.Error: |
|
662 return user_key.values() |
|
663 |
|
664 assert response.set_status_size() == len(server_keys) |
|
665 |
|
666 unset_list = [] |
|
667 for server_key, set_status in zip(server_keys, response.set_status_list()): |
|
668 if set_status != MemcacheSetResponse.STORED: |
|
669 unset_list.append(user_key[server_key]) |
|
670 |
|
671 return unset_list |
|
672 |
616 def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0): |
673 def set_multi(self, mapping, time=0, key_prefix='', min_compress_len=0): |
617 """Set multiple keys' values at once. |
674 """Set multiple keys' values at once, regardless of previous contents. |
618 |
|
619 This reduces the network latency of doing many requests in serial. |
|
620 |
675 |
621 Args: |
676 Args: |
622 mapping: Dictionary of keys to values. |
677 mapping: Dictionary of keys to values. |
623 time: Optional expiration time, either relative number of seconds |
678 time: Optional expiration time, either relative number of seconds |
624 from current time (up to 1 month), or an absolute Unix epoch time. |
679 from current time (up to 1 month), or an absolute Unix epoch time. |
630 |
685 |
631 Returns: |
686 Returns: |
632 A list of keys whose values were NOT set. On total success, |
687 A list of keys whose values were NOT set. On total success, |
633 this list should be empty. |
688 this list should be empty. |
634 """ |
689 """ |
635 if not isinstance(time, (int, long, float)): |
690 return self._set_multi_with_policy(MemcacheSetRequest.SET, mapping, |
636 raise TypeError('Expiration must be a number.') |
691 time=time, key_prefix=key_prefix) |
637 if time < 0.0: |
692 |
638 raise ValueError('Expiration must not be negative.') |
693 def add_multi(self, mapping, time=0, key_prefix='', min_compress_len=0): |
639 |
694 """Set multiple keys' values iff items are not already in memcache. |
640 request = MemcacheSetRequest() |
695 |
641 user_key = {} |
696 Args: |
642 server_keys = [] |
697 mapping: Dictionary of keys to values. |
643 for key, value in mapping.iteritems(): |
698 time: Optional expiration time, either relative number of seconds |
644 server_key = _key_string(key, key_prefix, user_key) |
699 from current time (up to 1 month), or an absolute Unix epoch time. |
645 stored_value, flags = _validate_encode_value(value, self._do_pickle) |
700 By default, items never expire, though items may be evicted due to |
646 server_keys.append(server_key) |
701 memory pressure. Float values will be rounded up to the nearest |
647 |
702 whole second. |
648 item = request.add_item() |
703 key_prefix: Prefix for to prepend to all keys. |
649 item.set_key(server_key) |
704 min_compress_len: Unimplemented compatibility option. |
650 item.set_value(stored_value) |
705 |
651 item.set_flags(flags) |
706 Returns: |
652 item.set_set_policy(MemcacheSetRequest.SET) |
707 A list of keys whose values were NOT set because they did not already |
653 item.set_expiration_time(int(math.ceil(time))) |
708 exist in memcache. On total success, this list should be empty. |
654 |
709 """ |
655 response = MemcacheSetResponse() |
710 return self._set_multi_with_policy(MemcacheSetRequest.ADD, mapping, |
656 try: |
711 time=time, key_prefix=key_prefix) |
657 self._make_sync_call('memcache', 'Set', request, response) |
712 |
658 except apiproxy_errors.ApplicationError: |
713 def replace_multi(self, mapping, time=0, key_prefix='', min_compress_len=0): |
659 return False |
714 """Replace multiple keys' values, failing if the items aren't in memcache. |
660 |
715 |
661 assert response.set_status_size() == len(server_keys) |
716 Args: |
662 |
717 mapping: Dictionary of keys to values. |
663 unset_list = [] |
718 time: Optional expiration time, either relative number of seconds |
664 for server_key, set_status in zip(server_keys, response.set_status_list()): |
719 from current time (up to 1 month), or an absolute Unix epoch time. |
665 if set_status != MemcacheSetResponse.STORED: |
720 By default, items never expire, though items may be evicted due to |
666 unset_list.append(user_key[server_key]) |
721 memory pressure. Float values will be rounded up to the nearest |
667 |
722 whole second. |
668 return unset_list |
723 key_prefix: Prefix for to prepend to all keys. |
|
724 min_compress_len: Unimplemented compatibility option. |
|
725 |
|
726 Returns: |
|
727 A list of keys whose values were NOT set because they already existed |
|
728 in memcache. On total success, this list should be empty. |
|
729 """ |
|
730 return self._set_multi_with_policy(MemcacheSetRequest.REPLACE, mapping, |
|
731 time=time, key_prefix=key_prefix) |
669 |
732 |
670 def incr(self, key, delta=1): |
733 def incr(self, key, delta=1): |
671 """Atomically increments a key's value. |
734 """Atomically increments a key's value. |
672 |
735 |
673 Internally, the value is a unsigned 64-bit integer. Memcache |
736 Internally, the value is a unsigned 64-bit integer. Memcache |
781 var_dict['get'] = _CLIENT.get |
846 var_dict['get'] = _CLIENT.get |
782 var_dict['get_multi'] = _CLIENT.get_multi |
847 var_dict['get_multi'] = _CLIENT.get_multi |
783 var_dict['set'] = _CLIENT.set |
848 var_dict['set'] = _CLIENT.set |
784 var_dict['set_multi'] = _CLIENT.set_multi |
849 var_dict['set_multi'] = _CLIENT.set_multi |
785 var_dict['add'] = _CLIENT.add |
850 var_dict['add'] = _CLIENT.add |
|
851 var_dict['add_multi'] = _CLIENT.add_multi |
786 var_dict['replace'] = _CLIENT.replace |
852 var_dict['replace'] = _CLIENT.replace |
|
853 var_dict['replace_multi'] = _CLIENT.replace_multi |
787 var_dict['delete'] = _CLIENT.delete |
854 var_dict['delete'] = _CLIENT.delete |
788 var_dict['delete_multi'] = _CLIENT.delete_multi |
855 var_dict['delete_multi'] = _CLIENT.delete_multi |
789 var_dict['incr'] = _CLIENT.incr |
856 var_dict['incr'] = _CLIENT.incr |
790 var_dict['decr'] = _CLIENT.decr |
857 var_dict['decr'] = _CLIENT.decr |
791 var_dict['flush_all'] = _CLIENT.flush_all |
858 var_dict['flush_all'] = _CLIENT.flush_all |