Skip to content

Instantly share code, notes, and snippets.

@sfitts
Created September 1, 2016 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfitts/6ac8fc6efa19ef86600ae5354682c5ca to your computer and use it in GitHub Desktop.
Save sfitts/6ac8fc6efa19ef86600ae5354682c5ca to your computer and use it in GitHub Desktop.
GridFS Read bug
package tests;
import com.google.common.primitives.Ints;
import com.mongodb.async.SingleResultCallback;
import com.mongodb.async.client.MongoClient;
import com.mongodb.async.client.MongoClients;
import com.mongodb.async.client.MongoDatabase;
import com.mongodb.async.client.gridfs.GridFSBucket;
import com.mongodb.async.client.gridfs.GridFSBuckets;
import com.mongodb.async.client.gridfs.GridFSDownloadStream;
import com.mongodb.async.client.gridfs.GridFSFindIterable;
import com.mongodb.async.client.gridfs.GridFSUploadStream;
import com.mongodb.client.gridfs.model.GridFSDownloadOptions;
import com.mongodb.client.gridfs.model.GridFSUploadOptions;
import io.vantiq.service.storage.mongodb.MongoServiceHelper;
import io.vertx.core.buffer.Buffer;
import lombok.Cleanup;
import org.bson.Document;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.concurrent.CountDownLatch;
/**
* Test which demonstrates a bug in the asycn driver's GridFS support.
*
* Created by sfitts on 9/1/16.
*/
public class GridFSBug {
private static final SecureRandom random = new SecureRandom();
private static class SingleResult<T> implements SingleResultCallback<T> {
private final CountDownLatch latch = new CountDownLatch(1);
private T result;
private Throwable t;
@Override
public void onResult(T result, Throwable t) {
this.t = t;
this.result = result;
latch.countDown();
}
T getResult() throws Throwable {
latch.await();
if (t != null) throw t;
return result;
}
}
private MongoClient client;
private GridFSBucket bucket;
@Before
public void openBucket() {
client = MongoClients.create();
MongoDatabase database = client.getDatabase("gridFSTest");
bucket = GridFSBuckets.create(database);
}
@After
public void cleanup() throws Throwable {
SingleResult<Void> done = new SingleResult<Void>();
GridFSFindIterable files = bucket.find();
files.forEach((file) -> {
try {
SingleResult<Void> deleteComplete = new SingleResult<Void>();
bucket.delete(file.getId(), deleteComplete);
deleteComplete.getResult();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}, done);
done.getResult();
}
@Test
public void testGridFSRead() throws Throwable {
// Open upload stream for file
int chunkSize = bucket.getChunkSizeBytes();
GridFSUploadOptions options = new GridFSUploadOptions().metadata(new Document("contentType", "application/octet"));
GridFSUploadStream uploadStrm = bucket.openUploadStream("testFile", options);
// Write 2 chunks of data to a file
for (int i = 0; i < 2; i++) {
ByteBuffer chunkData = ByteBuffer.allocate(chunkSize);
random.nextBytes(chunkData.array());
SingleResult<Integer> writeResult = new SingleResult<>();
uploadStrm.write(chunkData, writeResult);
int bytesWritten = writeResult.getResult();
Assert.assertEquals(chunkSize, bytesWritten);
}
// Close the stream
SingleResult<Void> completed = new SingleResult<Void>();
uploadStrm.close(completed);
completed.getResult();
// Now read back the data using a buffer which is smaller than the chunk size
GridFSDownloadStream downloadStrm = bucket.openDownloadStream("testFile", new GridFSDownloadOptions());
int bytesRead = 0;
while (bytesRead != -1) {
ByteBuffer dst = ByteBuffer.allocate(chunkSize / 2);
SingleResult<Integer> readResult = new SingleResult<>();
downloadStrm.read(dst, readResult);
bytesRead = readResult.getResult();
}
// Close the stream
completed = new SingleResult<Void>();
downloadStrm.close(completed);
completed.getResult();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment