1 | /** |
2 | * |
3 | * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com> |
4 | * |
5 | * ==================================================================== |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | * you may not use this file except in compliance with the License. |
8 | * You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, software |
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | * See the License for the specific language governing permissions and |
16 | * limitations under the License. |
17 | * ==================================================================== |
18 | */ |
19 | package org.jclouds.openstack.swift.blobstore; |
20 | |
21 | import static com.google.common.base.Preconditions.checkNotNull; |
22 | import static org.jclouds.blobstore.util.BlobStoreUtils.createParentIfNeededAsync; |
23 | |
24 | import java.util.Set; |
25 | import java.util.concurrent.ExecutorService; |
26 | |
27 | import javax.inject.Inject; |
28 | import javax.inject.Named; |
29 | import javax.inject.Provider; |
30 | import javax.inject.Singleton; |
31 | |
32 | import org.jclouds.Constants; |
33 | import org.jclouds.blobstore.BlobStoreContext; |
34 | import org.jclouds.blobstore.domain.Blob; |
35 | import org.jclouds.blobstore.domain.BlobMetadata; |
36 | import org.jclouds.blobstore.domain.PageSet; |
37 | import org.jclouds.blobstore.domain.StorageMetadata; |
38 | import org.jclouds.blobstore.domain.internal.PageSetImpl; |
39 | import org.jclouds.blobstore.functions.BlobToHttpGetOptions; |
40 | import org.jclouds.blobstore.internal.BaseAsyncBlobStore; |
41 | import org.jclouds.blobstore.options.ListContainerOptions; |
42 | import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; |
43 | import org.jclouds.blobstore.util.BlobUtils; |
44 | import org.jclouds.collect.Memoized; |
45 | import org.jclouds.concurrent.Futures; |
46 | import org.jclouds.domain.Location; |
47 | import org.jclouds.http.options.GetOptions; |
48 | import org.jclouds.openstack.swift.CommonSwiftAsyncClient; |
49 | import org.jclouds.openstack.swift.CommonSwiftClient; |
50 | import org.jclouds.openstack.swift.blobstore.functions.BlobStoreListContainerOptionsToListContainerOptions; |
51 | import org.jclouds.openstack.swift.blobstore.functions.BlobToObject; |
52 | import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceList; |
53 | import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceMetadata; |
54 | import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlob; |
55 | import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata; |
56 | import org.jclouds.openstack.swift.domain.ContainerMetadata; |
57 | import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata; |
58 | import org.jclouds.openstack.swift.domain.ObjectInfo; |
59 | import org.jclouds.openstack.swift.domain.SwiftObject; |
60 | |
61 | import com.google.common.base.Function; |
62 | import com.google.common.base.Supplier; |
63 | import com.google.common.collect.Iterables; |
64 | import com.google.common.util.concurrent.ListenableFuture; |
65 | |
66 | /** |
67 | * |
68 | * @author Adrian Cole |
69 | */ |
70 | @Singleton |
71 | public class SwiftAsyncBlobStore extends BaseAsyncBlobStore { |
72 | private final CommonSwiftClient sync; |
73 | private final CommonSwiftAsyncClient async; |
74 | private final ContainerToResourceMetadata container2ResourceMd; |
75 | private final BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions; |
76 | private final ContainerToResourceList container2ResourceList; |
77 | private final ObjectToBlob object2Blob; |
78 | private final BlobToObject blob2Object; |
79 | private final ObjectToBlobMetadata object2BlobMd; |
80 | private final BlobToHttpGetOptions blob2ObjectGetOptions; |
81 | private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider; |
82 | |
83 | @Inject |
84 | SwiftAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils, |
85 | @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation, |
86 | @Memoized Supplier<Set<? extends Location>> locations, CommonSwiftClient sync, CommonSwiftAsyncClient async, |
87 | ContainerToResourceMetadata container2ResourceMd, |
88 | BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions, |
89 | ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object, |
90 | ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions, |
91 | Provider<FetchBlobMetadata> fetchBlobMetadataProvider) { |
92 | super(context, blobUtils, service, defaultLocation, locations); |
93 | this.sync = sync; |
94 | this.async = async; |
95 | this.container2ResourceMd = container2ResourceMd; |
96 | this.container2ContainerListOptions = container2ContainerListOptions; |
97 | this.container2ResourceList = container2ResourceList; |
98 | this.object2Blob = object2Blob; |
99 | this.blob2Object = blob2Object; |
100 | this.object2BlobMd = object2BlobMd; |
101 | this.blob2ObjectGetOptions = blob2ObjectGetOptions; |
102 | this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider"); |
103 | } |
104 | |
105 | /** |
106 | * This implementation invokes {@link CommonSwiftAsyncClient#listContainers} |
107 | */ |
108 | @Override |
109 | public ListenableFuture<PageSet<? extends StorageMetadata>> list() { |
110 | return Futures.compose(async.listContainers(), |
111 | new Function<Set<ContainerMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() { |
112 | public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply( |
113 | Set<ContainerMetadata> from) { |
114 | return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), null); |
115 | } |
116 | }, service); |
117 | } |
118 | |
119 | /** |
120 | * This implementation invokes {@link CommonSwiftAsyncClient#containerExists} |
121 | * |
122 | * @param container |
123 | * container name |
124 | */ |
125 | @Override |
126 | public ListenableFuture<Boolean> containerExists(String container) { |
127 | return async.containerExists(container); |
128 | } |
129 | |
130 | /** |
131 | * Note that location is currently ignored. |
132 | */ |
133 | @Override |
134 | public ListenableFuture<Boolean> createContainerInLocation(Location location, String container) { |
135 | return async.createContainer(container); |
136 | } |
137 | |
138 | /** |
139 | * This implementation invokes {@link CommonSwiftAsyncClient#listBucket} |
140 | * |
141 | * @param container |
142 | * container name |
143 | */ |
144 | @Override |
145 | public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) { |
146 | org.jclouds.openstack.swift.options.ListContainerOptions httpOptions = container2ContainerListOptions |
147 | .apply(options); |
148 | ListenableFuture<PageSet<ObjectInfo>> returnVal = async.listObjects(container, httpOptions); |
149 | ListenableFuture<PageSet<? extends StorageMetadata>> list = Futures.compose(returnVal, container2ResourceList, |
150 | service); |
151 | return options.isDetailed() ? Futures.compose(list, fetchBlobMetadataProvider.get().setContainerName(container), |
152 | service) : list; |
153 | } |
154 | |
155 | /** |
156 | * This implementation invokes {@link CommonSwiftAsyncClient#objectExists} |
157 | * |
158 | * @param container |
159 | * container name |
160 | * @param key |
161 | * object key |
162 | */ |
163 | @Override |
164 | public ListenableFuture<Boolean> blobExists(String container, String key) { |
165 | return async.objectExists(container, key); |
166 | } |
167 | |
168 | /** |
169 | * This implementation invokes {@link CommonSwiftAsyncClient#headObject} |
170 | * |
171 | * @param container |
172 | * container name |
173 | * @param key |
174 | * object key |
175 | */ |
176 | @Override |
177 | public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) { |
178 | return Futures.compose(async.getObjectInfo(container, key), |
179 | new Function<MutableObjectInfoWithMetadata, BlobMetadata>() { |
180 | |
181 | @Override |
182 | public BlobMetadata apply(MutableObjectInfoWithMetadata from) { |
183 | return object2BlobMd.apply(from); |
184 | } |
185 | |
186 | }, service); |
187 | } |
188 | |
189 | /** |
190 | * This implementation invokes {@link CommonSwiftAsyncClient#getObject} |
191 | * |
192 | * @param container |
193 | * container name |
194 | * @param key |
195 | * object key |
196 | */ |
197 | @Override |
198 | public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) { |
199 | GetOptions httpOptions = blob2ObjectGetOptions.apply(options); |
200 | ListenableFuture<SwiftObject> returnVal = async.getObject(container, key, httpOptions); |
201 | return Futures.compose(returnVal, object2Blob, service); |
202 | } |
203 | |
204 | /** |
205 | * This implementation invokes {@link CommonSwiftAsyncClient#putObject} |
206 | * |
207 | * @param container |
208 | * container name |
209 | * @param blob |
210 | * object |
211 | */ |
212 | @Override |
213 | public ListenableFuture<String> putBlob(String container, Blob blob) { |
214 | createParentIfNeededAsync(this, container, blob); |
215 | return async.putObject(container, blob2Object.apply(blob)); |
216 | } |
217 | |
218 | /** |
219 | * This implementation invokes {@link CommonSwiftAsyncClient#removeObject} |
220 | * |
221 | * @param container |
222 | * container name |
223 | * @param key |
224 | * object key |
225 | */ |
226 | @Override |
227 | public ListenableFuture<Void> removeBlob(String container, String key) { |
228 | return async.removeObject(container, key); |
229 | } |
230 | |
231 | @Override |
232 | protected boolean deleteAndVerifyContainerGone(String container) { |
233 | sync.deleteContainerIfEmpty(container); |
234 | return !sync.containerExists(container); |
235 | } |
236 | |
237 | } |