Index: trunk/extensions/SwiftMedia/SwiftMedia.body.php |
— | — | @@ -91,7 +91,7 @@ |
92 | 92 | |
93 | 93 | parent::__construct( $title, $repo ); |
94 | 94 | |
95 | | - $this->tempPath = false; // Points to our local copy. |
| 95 | + $this->tempPaths = array(); // Hash from rel to local copy. |
96 | 96 | } |
97 | 97 | |
98 | 98 | /** splitMime inherited */ |
— | — | @@ -101,33 +101,61 @@ |
102 | 102 | /** getViewURL inherited */ |
103 | 103 | /** isVisible inherited */ |
104 | 104 | |
| 105 | + /** |
| 106 | + * We're re-purposing getPath() to checkout a copy of the file, if we don't already have a copy. |
| 107 | + * |
| 108 | + * @return string Path to a local copy of the file. |
| 109 | + */ |
105 | 110 | public function getPath() { |
106 | | - $this->tempPath = $this->repo->getLocalCopy( $this->repo->container, $this->getRel() ); |
107 | | - return $this->tempPath; |
| 111 | + if ( !$this->TempPaths[''] ) { |
| 112 | + $this->tempPaths[''] = $this->repo->getLocalCopy( $this->repo->container, $this->getRel(), 'getPath' ); |
| 113 | + } |
| 114 | + return $this->tempPaths['']; |
108 | 115 | } |
109 | 116 | |
110 | | - /** Get the path of the archive directory, or a particular file if $suffix is specified */ |
111 | | - public function getArchivePath( $suffix = false ) { |
112 | | - $this->tempPath = $this->repo->getLocalCopy( $this->repo->getZoneContainer( 'public' ), $this->getArchiveRel( $suffix ) ); |
113 | | - return $this->tempPath; |
| 117 | + /** |
| 118 | + * We're re-purposing getPath() to checkout a copy of the file, if we don't already have a copy. |
| 119 | + * Get a local copy of a particular archived file specified by $suffix |
| 120 | + * |
| 121 | + * @param string suffix Specific archived copy. |
| 122 | + * @return string Path to a local copy of the file. |
| 123 | + */ |
| 124 | + public function getArchivePath( $suffix = false) { |
| 125 | + if (!$suffix) { |
| 126 | + throw new MWException( "Can't call getArchivePath without a suffix" ); |
| 127 | + } |
| 128 | + $rel = $this->getArchiveRel( $suffix ); |
| 129 | + if ( !array_key_exists($rel, $this->tempPaths ) ) { |
| 130 | + $this->tempPaths[$rel] = $this->repo->getLocalCopy( $this->repo->container, $rel ); |
| 131 | + } |
| 132 | + return $this->tempPaths[$rel]; |
114 | 133 | } |
115 | 134 | |
116 | | - /** Get the path of the thumbnail directory, or a particular file if $suffix is specified */ |
117 | | - public function getThumbPath( $suffix = false ) { |
118 | | - $path = $this->getRel(); |
119 | | - if ( $suffix !== false ) { |
120 | | - $path .= '/' . $suffix; |
| 135 | + /** |
| 136 | + * We're re-purposing getPath() to checkout a copy of the file, if we don't already have a copy. |
| 137 | + * Get a local copy of a particular thumb specified by $suffix |
| 138 | + * |
| 139 | + * @param string suffix Specific thumbnail. |
| 140 | + * @return string Path to a local copy of the file. |
| 141 | + */ |
| 142 | + public function getThumbPath( $suffix = false) { |
| 143 | + if (!$suffix) { |
| 144 | + throw new MWException( "Can't call getThumbPath without a suffix" ); |
121 | 145 | } |
122 | | - $this->tempPath = $this->repo->getLocalCopy( $this->repo->getZoneContainer( 'thumb' ), $path ); |
123 | | - return $this->tempPath; |
124 | | - } |
| 146 | + $rel = $this->getRel() . '/' . $suffix; |
| 147 | + if ( !array_key_exists($rel, $this->tempPaths ) ) { |
| 148 | + $this->tempPaths[$rel] = $this->repo->getLocalCopy( $this->repo->getZoneContainer( 'thumb' ), $rel ); |
| 149 | + } |
| 150 | + return $this->tempPaths[$rel]; |
| 151 | + } |
125 | 152 | |
126 | 153 | function __destruct() { |
127 | | - if ( $this->tempPath ) { |
| 154 | + foreach ( $this->tempPaths as $path) { |
128 | 155 | // Clean up temporary data. |
129 | | - unlink( $this->tempPath ); |
130 | | - $this->tempPath = null; |
| 156 | + wfDebug( __METHOD__ . ": deleting $path\n" ); |
| 157 | + unlink( $path ); |
131 | 158 | } |
| 159 | + $this->tempPaths = array(); |
132 | 160 | } |
133 | 161 | |
134 | 162 | /** |
— | — | @@ -146,7 +174,10 @@ |
147 | 175 | global $wgIgnoreImageErrors, $wgThumbnailEpoch, $wgTmpDirectory; |
148 | 176 | |
149 | 177 | // get a temporary place to put the original. |
150 | | - $thumbPath = tempnam( $wgTmpDirectory, 'transform_out_' ) . '.' . pathinfo( $thumbName, PATHINFO_EXTENSION ); |
| 178 | + $thumbPath = tempnam( $wgTmpDirectory, 'transform_out_' ); |
| 179 | + unlink( $thumbPath ); |
| 180 | + $thumbPath .= '.' . pathinfo( $thumbName, PATHINFO_EXTENSION ); |
| 181 | + |
151 | 182 | |
152 | 183 | if ( $this->repo && $this->repo->canTransformVia404() && !( $flags & self::RENDER_NOW ) ) { |
153 | 184 | return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); |
— | — | @@ -912,10 +943,12 @@ |
913 | 944 | * SwiftFile->tempPath so it will be deleted when the object goes out of |
914 | 945 | * scope. |
915 | 946 | */ |
916 | | - function getLocalCopy( $container, $rel ) { |
| 947 | + function getLocalCopy( $container, $rel, $prefix = 'swift_in_' ) { |
917 | 948 | |
918 | 949 | // get a temporary place to put the original. |
919 | | - $tempPath = tempnam( wfTempDir(), 'swift_in_' ) . '.' . pathinfo( $rel, PATHINFO_EXTENSION ); |
| 950 | + $tempPath = tempnam( wfTempDir(), $prefix ); |
| 951 | + unlink( $tempPath ); |
| 952 | + $tempPath .= '.' . pathinfo( $rel, PATHINFO_EXTENSION ); |
920 | 953 | |
921 | 954 | /* Fetch the image out of Swift */ |
922 | 955 | $conn = $this->connect(); |
Index: trunk/extensions/SwiftMedia/TODO |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | Should UploadStashFile *always* (in our case) be called with a virtual URL? |
19 | 19 | 23) TS: "When you get around to implementing SwiftRepo::append(), it will need some sort of concurrency control to avoid having chunks overwrite each other. " |
20 | 20 | 24) TS: "SwiftRepo::swiftcopy() should return a Status object instead of throwing exceptions." |
| 21 | +26) Hazmat wonders what happens if two clients fetch missing thumbnails at the same time. What happens when you have overlapping writes to the same object. |
21 | 22 | |
22 | 23 | Partially resolved: |
23 | 24 | |