Skip to content

Commit cc0c05c

Browse files
Gopal-Moolchandanidasiyogesh
authored andcommitted
ZBUG-4409: Missing Blobs on a restored account from backup with S3 storage
Refactored according to review comments Refactored Refactoring the testing classes Refactored according to the review comments ZBUG-4409 Added Ldap attribute for JUNIT
1 parent 8012084 commit cc0c05c

File tree

7 files changed

+120
-1
lines changed

7 files changed

+120
-1
lines changed

store/src/java-test/com/zimbra/cs/account/MockProvisioning.java

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public MockProvisioning() {
8585
attrs.put(A_zimbraSmtpPort, "7025");
8686
attrs.put(A_zimbraLowestSupportedAuthVersion, "1");
8787
attrs.put(A_zimbraSSLPrivateKey, "-----BEGIN PRIVATE KEY-----MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDj5CdJz5QNpk7skWqv7lC7gaymGiqbpEXAe8za1JTgjKkL0gzQNM79aGr+lnYKXU+rto15QT9uDyvVnY/iPlpeLtCEin9OIEccLsPivG0R8gL8O2HGF86ns+ZNbjjJVetr/qk1mFN/91qMfOhL/F6tBR5zSIVdCE4bdqCqpq4HywEaKyXxCwU4bKlmawrLRZeITiMQ6Je/VsFvz2wj7yrlCH5HKtoyaNuLR9KH1HHbFB/p9JCK9/qZpq5p4vNXr0fGs3PFQAfhau2ySmo1bEhYDIs3/nBLrXP3OHQqfEPEE1R7BrcEBBtUaY8t5JSduOQRr63qDyGjXnu+xcwA46v/AgMBAAECggEAUa57LoeKZ4IOk9hjRv/CTBLkkPyb/QFaRu2YtW6wlfOUu7nkAdSLxGRixTGkyX48ii16c9WhKI+jhINfCRaUSWG6N2d0zcnf8wgICgLDjUUTMNkP6HKsDYv7phE1pWR4Z1L1z1Hzy9Aa0nQKxwGD5bwJ+AQsWPYbGNjiKYhopD2/zbTnhhYCA9/aSf2vKUa9ITWpW7nbYK1dtOW+eX+CrBRBO54KQ0OlJBnzk2oZv7IOlp6PUck0HMurP/N/EV1lVwvsMaddy3osHrB1qjA/vSX+wYMaNRSyN8p9hRTAAPQKJKy3feXUrE/kzhV/MP0DYbHkV1SYDNt0nDarZ8wDAQKBgQD2r0UIdMmOwjGoR0y4/EXSvEf6+KP+t0GDEYfl9C5/Ei3BTFPU5bWg/1TEQJ5R4AsI6TchHE1k0o1tENZ09SO/9ESQPfRZHbbaMit64SAg3e8mvChEvVfaunDapOTuwiqzvTjc12plwXrzrkt2xtXLpWvZ8afWVaBhEZysieXvQQKBgQDsfzSc4AuUprqqLU7pyQGSy9zjv2Pt25aUdiyiVYawzDfcQly4x5b/b/NodQ2SG/5zN2/L+fvjHJvWcKsHx984siOGVMxEK5uUz00eKbVB/PZP+oT7MALStaI0U0gnwtnWgXCxMKl2QOfWnF3AMkF99xKywsuyFIg6ojoE9IYLPwKBgQDzxmi13pOAXC+uWCdddw+ZHS8UuLl3calv2NcvS4rXUCOfLcp6TTacDza5ahIKXxkIiU9NjSZ+SAQyj70ef1IA02ceE9twZYjZP1Lwb6DMWgWHhdFVfLdhE3WK3ADQYVjJnmie9NHUFMtoHAm/KucEBEj8a26sxJlk0368ktmDAQKBgBGMctv9J/7UzF8aU5O3bZ118SMZLZIVzDuh9Tfqfr8ZuD9o0TaI4OR9ayNiJCqmVyA3id0p5I36rnmgDKDcLO0pEsfB/RJF5hqJs2A8mg2WdrSCk2GMM3ltLucREvaYV8+59SHAyaJTuKBNJAvB7ugo8ENBfxnsuhsXtJRvjI7DAoGAG7HrReM3cX8k8jqopY8xlT03Q372v07PL8fs2aOP+zsA580IdDw0Xvea+dmykCzpj3DmBci+TOE7DYb1SW6+NPN4FOP6o6TFogrgNa/0LAWXPuct+1e5vy9F1/jFpvNbbD8uTJKdJWGKO78wLVybn9gTJ95ZZcBfytQMyXpqysk=-----END PRIVATE KEY-----");
88+
attrs.put(A_zimbraMailboxMoveTempDir,System.getProperty("java.io.tmpdir")+ "/" + "testFileUtil");
8889
localhost = new Server("localhost", "localhost", attrs, Collections.<String, Object>emptyMap(), this);
8990
servers.put("localhost", localhost);
9091
try {

store/src/java-test/com/zimbra/cs/store/MockStoreManager.java

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.HashMap;
2828
import java.util.Map;
2929

30+
import com.zimbra.cs.volume.Volume;
3031
import org.apache.commons.io.output.ByteArrayOutputStream;
3132

3233
import com.google.common.io.ByteStreams;
@@ -106,6 +107,11 @@ public StagedBlob stage(InputStream data, long actualSize, Mailbox mbox) throws
106107
return new MockStagedBlob(mbox, ByteStreams.toByteArray(data));
107108
}
108109

110+
@Override
111+
public StagedBlob stage(InputStream data, long actualSize, Mailbox mbox, Volume volume) throws IOException {
112+
return new MockStagedBlob(mbox, ByteStreams.toByteArray(data));
113+
}
114+
109115
@Override
110116
public StagedBlob stage(Blob blob, Mailbox mbox) {
111117
return new MockStagedBlob(mbox, ((MockBlob) blob).content);

store/src/java-test/com/zimbra/cs/store/StoreManagerAfterReset.java

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.zimbra.common.service.ServiceException;
2020
import com.zimbra.cs.mailbox.Mailbox;
21+
import com.zimbra.cs.volume.Volume;
2122

2223
import java.io.IOException;
2324
import java.io.InputStream;
@@ -59,6 +60,11 @@ public StagedBlob stage(InputStream data, long actualSize, Mailbox mbox) throws
5960
return null;
6061
}
6162

63+
@Override
64+
public StagedBlob stage(InputStream data, long actualSize, Mailbox mbox, Volume volume) throws IOException, ServiceException {
65+
throw ServiceException.UNSUPPORTED();
66+
}
67+
6268
@Override
6369
public StagedBlob stage(Blob blob, Mailbox mbox) throws IOException, ServiceException {
6470
return null;

store/src/java/com/zimbra/cs/store/StoreManager.java

+32-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.zimbra.cs.store.file.FileBlobStore;
3030
import com.zimbra.cs.store.helper.ClassHelper;
3131
import com.zimbra.cs.util.Zimbra;
32+
import com.zimbra.cs.volume.Volume;
3233
import com.zimbra.cs.volume.VolumeManager;
3334

3435
import java.io.IOException;
@@ -46,6 +47,7 @@ public abstract class StoreManager {
4647
*/
4748
private static short currentVolumeId;
4849
private static Integer diskStreamingThreshold;
50+
private static final int actualSizeforUnstagedBlob = -1;
4951

5052

5153
public static StoreManager getInstance () {
@@ -292,6 +294,20 @@ public abstract Blob storeIncoming(InputStream data, boolean storeAsIs)
292294
public abstract StagedBlob stage(InputStream data, long actualSize, Mailbox mbox)
293295
throws IOException, ServiceException;
294296

297+
/**
298+
* Stage an incoming <code>InputStream</code> to an
299+
* appropriate place for subsequent storage in a <code>Mailbox</code> via
300+
* {@link #link(StagedBlob, Mailbox, int, int)} or {@link #renameTo}.
301+
*
302+
* @param data the data stream
303+
* @param actualSize the content size, or {@code -1} if the content size is not available
304+
* @param callback callback, or {@code null}
305+
* @param mbox the mailbox
306+
* @param volume the volume
307+
*/
308+
public abstract StagedBlob stage(InputStream data, long actualSize, Mailbox mbox, Volume volume)
309+
throws IOException, ServiceException;
310+
295311
/**
296312
* Stage an incoming <code>InputStream</code> to an
297313
* appropriate place for subsequent storage in a <code>Mailbox</code> via
@@ -303,7 +319,22 @@ public abstract StagedBlob stage(InputStream data, long actualSize, Mailbox mbox
303319
*/
304320
public StagedBlob stage(InputStream data, Mailbox mbox)
305321
throws IOException, ServiceException {
306-
return stage(data, -1, mbox);
322+
return stage(data, actualSizeforUnstagedBlob, mbox);
323+
}
324+
325+
/**
326+
* Stage an incoming <code>InputStream</code> to an
327+
* appropriate place for subsequent storage in a <code>Mailbox</code> via
328+
* {@link #link(StagedBlob, Mailbox, int, int)} or {@link #renameTo}.
329+
*
330+
* @param data the data stream
331+
* @param callback callback, or {@code null}
332+
* @param mbox the mailbox
333+
* @param volume the volume
334+
*/
335+
public StagedBlob stage(InputStream data, Mailbox mbox, Volume volume)
336+
throws IOException, ServiceException {
337+
return stage(data, actualSizeforUnstagedBlob, mbox, volume);
307338
}
308339

309340
/**

store/src/java/com/zimbra/cs/store/external/ExternalBlobIO.java

+15
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ public interface ExternalBlobIO {
3838
*/
3939
String writeStreamToStore(InputStream in, long actualSize, Mailbox mbox) throws IOException, ServiceException;
4040

41+
/**
42+
* Write data to blob store
43+
*
44+
* @param in: InputStream containing data to be written
45+
* @param actualSize: size of data in stream, or -1 if size is unknown. To be used by implementor for optimization where possible
46+
* @param mbox: Mailbox which contains the blob. Can optionally be used by store for partitioning
47+
* @param destVolId: Destination Volume id on which we need to store the blob
48+
* @return locator string for the stored blob, unique identifier created by storage protocol
49+
* @throws IOException
50+
* @throws ServiceException
51+
*/
52+
default String writeStreamToStore(InputStream in, long actualSize, Mailbox mbox, short destVolId) throws IOException, ServiceException {
53+
throw ServiceException.UNSUPPORTED();
54+
}
55+
4156
/**
4257
* Create an input stream for reading data from blob store
4358
* @param locator: identifier string for the blob as returned from write operation

store/src/java/com/zimbra/cs/store/external/ExternalStoreManager.java

+54
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import com.zimbra.cs.store.StagedBlob;
4545
import com.zimbra.cs.store.StoreManager;
4646
import com.zimbra.cs.store.file.VolumeMailboxBlob;
47+
import com.zimbra.cs.volume.Volume;
4748

4849
/**
4950
* Abstract base class for external store integration.
@@ -272,6 +273,31 @@ public StagedBlob stage(Blob blob, Mailbox mbox) throws IOException, ServiceExce
272273
}
273274
}
274275

276+
public StagedBlob stage(Blob blob, Mailbox mbox, Volume volume) throws IOException, ServiceException {
277+
if (supports(StoreFeature.RESUMABLE_UPLOAD) && blob instanceof ExternalUploadedBlob) {
278+
ZimbraLog.store.debug("blob already uploaded, just need to commit");
279+
String locator = ((ExternalResumableUpload) this).finishUpload((ExternalUploadedBlob) blob);
280+
if (null != locator) {
281+
ZimbraLog.store.debug("wrote to locator %s", locator);
282+
localCache.put(locator, getContent(blob));
283+
} else {
284+
ZimbraLog.store.warn("blob staging returned null locator");
285+
}
286+
return new ExternalStagedBlob(mbox, blob.getDigest(), blob.getRawSize(), locator);
287+
} else {
288+
InputStream is = getContent(blob);
289+
try {
290+
StagedBlob staged = stage(is, blob.getRawSize(), mbox, volume);
291+
if (null != staged && null != staged.getLocator()) {
292+
localCache.put(staged.getLocator(), getContent(blob));
293+
}
294+
return staged;
295+
} finally {
296+
ByteUtil.closeStream(is);
297+
}
298+
}
299+
}
300+
275301
@Override
276302
public StagedBlob stage(InputStream in, long actualSize, Mailbox mbox) throws ServiceException, IOException {
277303
if (actualSize < 0) {
@@ -303,7 +329,35 @@ public StagedBlob stage(InputStream in, long actualSize, Mailbox mbox) throws Se
303329
}
304330
}
305331

332+
public StagedBlob stage(InputStream in, long actualSize, Mailbox mbox, Volume volume) throws ServiceException, IOException {
333+
if (actualSize < 0) {
334+
Blob blob = storeIncoming(in);
335+
try {
336+
return stage(blob, mbox, volume);
337+
} finally {
338+
quietDelete(blob);
339+
}
340+
}
341+
MessageDigest digest;
342+
try {
343+
digest = MessageDigest.getInstance("SHA-256");
344+
} catch (NoSuchAlgorithmException e) {
345+
throw ServiceException.FAILURE("SHA-256 digest not found", e);
346+
}
347+
ByteUtil.PositionInputStream pin = new ByteUtil.PositionInputStream(new DigestInputStream(in, digest));
306348

349+
try {
350+
String locator = writeStreamToStore(pin, actualSize, mbox, volume.getId());
351+
if (null != locator) {
352+
ZimbraLog.store.debug("wrote to locator %s",locator);
353+
} else {
354+
ZimbraLog.store.warn("blob staging returned null locator");
355+
}
356+
return new ExternalStagedBlob(mbox, ByteUtil.encodeFSSafeBase64(digest.digest()), pin.getPosition(), locator);
357+
} catch (IOException e) {
358+
throw ServiceException.FAILURE("unable to stage blob", e);
359+
}
360+
}
307361
@Override
308362
public Blob storeIncoming(InputStream data, boolean storeAsIs) throws IOException,
309363
ServiceException {

store/src/java/com/zimbra/cs/store/file/FileBlobStore.java

+6
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ public VolumeStagedBlob stage(InputStream in, long actualSize, Mailbox mbox)
118118
return new VolumeStagedBlob(mbox, (VolumeBlob) blob).markStagedDirectly();
119119
}
120120

121+
@Override
122+
public StagedBlob stage(InputStream data, long actualSize, Mailbox mbox, Volume volume) throws IOException, ServiceException {
123+
// mailbox store is on the same volume as incoming directory, so no need to stage the blob
124+
throw ServiceException.FAILURE("Operation can not be completed because the required StoreManager is not available", null);
125+
}
126+
121127
@Override
122128
public VolumeStagedBlob stage(Blob blob, Mailbox mbox) throws IOException {
123129
// mailbox store is on the same volume as incoming directory, so no need to stage the blob

0 commit comments

Comments
 (0)