[Zope-Checkins] CVS: Zope/lib/python/OFS - Image.py:1.124.4.5

Martijn Pieters mj@zope.com
Wed, 21 Aug 2002 17:44:43 -0400


Update of /cvs-repository/Zope/lib/python/OFS
In directory cvs.zope.org:/tmp/cvs-serv18973/OFS

Modified Files:
      Tag: zope-2_3-branch
	Image.py 
Log Message:
Merge of byte range fix for the benefit of Zope.org.


=== Zope/lib/python/OFS/Image.py 1.124.4.4 => 1.124.4.5 ===
--- Zope/lib/python/OFS/Image.py:1.124.4.4	Sat Jul 13 17:14:24 2002
+++ Zope/lib/python/OFS/Image.py	Wed Aug 21 17:44:13 2002
@@ -290,8 +290,7 @@
                     RESPONSE.setStatus(416)
                     return ''
 
-                # Can we optimize?
-                ranges = HTTPRangeSupport.optimizeRanges(ranges, self.size)
+                ranges = HTTPRangeSupport.expandRanges(ranges, self.size)
                                 
                 if len(ranges) == 1:
                     # Easy case, set extra header and return partial set.
@@ -338,9 +337,6 @@
                     return ''
                     
                 else:
-                    # When we get here, ranges have been optimized, so they are
-                    # in order, non-overlapping, and start and end values are
-                    # positive integers.
                     boundary = choose_boundary()
                     
                     # Calculate the content length
@@ -367,8 +363,11 @@
                             draftprefix, boundary))
                     RESPONSE.setStatus(206) # Partial content
 
-                    pos = 0
                     data = self.data
+                    # The Pdata map allows us to jump into the Pdata chain
+                    # arbitrarily during out-of-order range searching.
+                    pdata_map = {}
+                    pdata_map[0] = data
 
                     for start, end in ranges:
                         RESPONSE.write('\r\n--%s\r\n' % boundary)
@@ -382,7 +381,14 @@
                             RESPONSE.write(data[start:end])
 
                         else:
-                            # Yippee. Linked Pdata objects.
+                            # Yippee. Linked Pdata objects. The following
+                            # calculations allow us to fast-forward through the
+                            # Pdata chain without a lot of dereferencing if we
+                            # did the work already.
+                            closest_pos = start - (start % (1<<16))
+                            pos = min(closest_pos, max(pdata_map.keys()))
+                            data = pdata_map[pos]
+
                             while data is not None:
                                 l = len(data.data)
                                 pos = pos + l
@@ -398,16 +404,18 @@
                                         
                                         # Send and loop to next range
                                         RESPONSE.write(data[lstart:lend])
-                                        # Back up the position marker, it will
-                                        # be incremented again for the next
-                                        # part.
-                                        pos = pos - l
                                         break
 
                                     # Not yet at the end, transmit what we have.
                                     RESPONSE.write(data[lstart:])
 
                                 data = data.next
+                                # Store a reference to a Pdata chain link so we
+                                # don't have to deref during this request again.
+                                pdata_map[pos] = data
+
+                    # Do not keep the link references around.
+                    del pdata_map
 
                     RESPONSE.write('\r\n--%s--\r\n' % boundary)
                     return ''