Revision 776b275c kamaki/clients/pithos/__init__.py

b/kamaki/clients/pithos/__init__.py
52 52
    return h.hexdigest()
53 53

  
54 54

  
55
def _range_up(start, end, a_range):
56
    if a_range:
57
        rstart, sep, rend = a_range.partition('-')
58
        if rstart:
55
def _range_up(start, end, max_value, a_range):
56
    """
57
    :param start: (int) the window bottom
58

  
59
    :param end: (int) the window top
60

  
61
    :param max_value: (int) maximum accepted value
62

  
63
    :param a_range: (str) a range string in the form X[,X'[,X''[...]]]
64
        where X: x|x-y|-x where x < y and x, y natural numbers
65

  
66
    :returns: (str) a range string cut-off for the start-end range
67
        an empty response means this window is out of range
68
    """
69
    assert start >= 0, '_range_up was called with start < 0'
70
    assert end >= start, '_range_up was called with end < start'
71
    assert end <= max_value, '_range_up was called with max_value < end'
72
    if not a_range:
73
        return '%s-%s' % (start, end)
74
    selected = []
75
    for some_range in a_range.split(','):
76
        v0, sep, v1 = some_range.partition('-')
77
        if v0:
78
            v0 = int(v0)
59 79
            if sep:
60
                rstart, rend = int(rstart), int(rend)
80
                v1 = int(v1)
81
                if v1 < start or v0 > end or v1 < v0:
82
                    continue
83
                v0 = v0 if v0 > start else start
84
                v1 = v1 if v1 < end else end
85
                selected.append('%s-%s' % (v0, v1))
86
            elif v0 < start:
87
                continue
61 88
            else:
62
                rstart, rend = 0, int(rstart)
63
        elif sep:
64
            return (0, - int(rend))
89
                v1 = v0 if v0 <= end else end
90
                selected.append('%s-%s' % (start, v1))
65 91
        else:
66
            return (0, 0)
67
        if rstart > end or rend < start:
68
            return (0, 0)
69
        if rstart > start:
70
            start = rstart
71
        if rend < end:
72
            end = rend
73
    return (start, end)
92
            v1 = int(v1)
93
            if max_value - v1 > end:
94
                continue
95
            v0 = (max_value - v1) if max_value - v1 > start else start
96
            selected.append('%s-%s' % (v0, end))
97
    return ','.join(selected)
74 98

  
75 99

  
76 100
class PithosClient(PithosRestClient):
......
641 665
                start = blocksize * blockid
642 666
                is_last = start + blocksize > total_size
643 667
                end = (total_size - 1) if is_last else (start + blocksize - 1)
644
                (start, end) = _range_up(start, end, crange)
645
                args['data_range'] = 'bytes=%s-%s' % (
646
                    (start, end) if end >= 0 else ('', - end))
668
                data_range = _range_up(start, end, total_size, crange)
669
                if not data_range:
670
                    self._cb_next()
671
                    continue
672
                args['data_range'] = 'bytes=%s' % data_range
647 673
                r = self.object_get(obj, success=(200, 206), **args)
648 674
                self._cb_next()
649 675
                dst.write(r.content)
......
689 715
        flying = dict()
690 716
        blockid_dict = dict()
691 717
        offset = 0
692
        if filerange is not None:
693
            rstart = int(filerange.split('-')[0])
694
            offset = rstart if blocksize > rstart else rstart % blocksize
695 718

  
696 719
        self._init_thread_limit()
697 720
        for block_hash, blockids in remote_hashes.items():
......
708 731
                    **restargs)
709 732
                end = total_size - 1 if (
710 733
                    key + blocksize > total_size) else key + blocksize - 1
711
                start, end = _range_up(key, end, filerange)
712
                if start == end:
734
                data_range = _range_up(key, end, total_size, filerange)
735
                if not data_range:
713 736
                    self._cb_next()
714 737
                    continue
715
                restargs['async_headers'] = {
716
                    'Range': 'bytes=%s-%s' % (
717
                        (start, end) if end >= 0 else ('', - end))}
738
                restargs['async_headers'] = {'Range': 'bytes=%s' % data_range}
718 739
                flying[key] = self._get_block_async(obj, **restargs)
719 740
                blockid_dict[key] = unsaved
720 741

  
......
857 878
                start = blocksize * blockid
858 879
                is_last = start + blocksize > total_size
859 880
                end = (total_size - 1) if is_last else (start + blocksize - 1)
860
                (start, end) = _range_up(start, end, range_str)
861
                if start < end or end < 0:
881
                data_range_str = _range_up(start, end, end, range_str)
882
                if data_range_str:
862 883
                    self._watch_thread_limit(flying.values())
884
                    restargs['data_range'] = 'bytes=%s' % data_range_str
863 885
                    flying[blockid] = self._get_block_async(obj, **restargs)
864 886
                for runid, thread in flying.items():
865 887
                    if (blockid + 1) == num_of_blocks:
......
899 921
            if_match=None,
900 922
            if_none_match=None,
901 923
            if_modified_since=None,
902
            if_unmodified_since=None,
903
            data_range=None):
924
            if_unmodified_since=None):
904 925
        """
905 926
        :param obj: (str) remote object path
906 927

  
......
912 933

  
913 934
        :param if_unmodified_since: (str) formated date
914 935

  
915
        :param data_range: (str) from-to where from and to are integers
916
            denoting file positions in bytes
917

  
918 936
        :returns: (list)
919 937
        """
920 938
        try:
......
925 943
                if_etag_match=if_match,
926 944
                if_etag_not_match=if_none_match,
927 945
                if_modified_since=if_modified_since,
928
                if_unmodified_since=if_unmodified_since,
929
                data_range=data_range)
946
                if_unmodified_since=if_unmodified_since)
930 947
        except ClientError as err:
931 948
            if err.status == 304 or err.status == 412:
932 949
                return {}

Also available in: Unified diff