Skip to content

Commit b44ea9f

Browse files
author
Hideki Itakura
committed
Fixed storing gzipped attachment.
1 parent 725e73a commit b44ea9f

2 files changed

Lines changed: 49 additions & 39 deletions

File tree

src/main/java/com/couchbase/lite/Attachment.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
import com.couchbase.lite.internal.InterfaceAudience;
2222
import com.couchbase.lite.util.Log;
2323

24-
import java.io.IOException;
2524
import java.io.File;
25+
import java.io.IOException;
2626
import java.io.InputStream;
2727
import java.net.URL;
2828
import java.util.Collections;
@@ -132,7 +132,7 @@ public InputStream getContent() throws CouchbaseLiteException {
132132
throw new CouchbaseLiteException(Status.INTERNAL_SERVER_ERROR);
133133
}
134134
Attachment attachment = db.getAttachmentForSequence(sequence, this.name);
135-
body = attachment.getContent();
135+
body = attachment.getBodyIfNew();
136136
if (attachment.getGZipped()) {
137137
// Client does not expect a gzipped stream.
138138
// Only Router handles gzipped streams and uses getAttachmentForSequence directly.

src/main/java/com/couchbase/lite/Database.java

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,8 @@ public synchronized boolean open() {
12691269
"key BLOB NOT NULL, " +
12701270
"type TEXT, " +
12711271
"length INTEGER NOT NULL, " +
1272+
"encoding INTEGER DEFAULT 0, " +
1273+
"encoded_length INTEGER, " +
12721274
"revpos INTEGER DEFAULT 0); " +
12731275
"CREATE INDEX attachments_by_sequence on attachments(sequence, filename); " +
12741276
"CREATE INDEX attachments_sequence ON attachments(sequence); " +
@@ -1297,9 +1299,16 @@ public synchronized boolean open() {
12971299
int revPos = (Integer) attachment.get("revpos");
12981300
int length = (Integer) attachment.get("length");
12991301
String digest = (String) attachment.get("digest");
1302+
int encodedLength = -1;
1303+
if(attachment.containsKey("encoded_length"))
1304+
encodedLength = (Integer)attachment.get("encoded_length");
1305+
AttachmentInternal.AttachmentEncoding encoding = AttachmentInternal.AttachmentEncoding.AttachmentEncodingNone;
1306+
if(attachment.containsKey("encoding") && attachment.get("encoding").equals("gzip")){
1307+
encoding = AttachmentInternal.AttachmentEncoding.AttachmentEncodingGZIP;
1308+
}
13001309
BlobKey key = new BlobKey(digest);
13011310
try {
1302-
insertAttachmentForSequenceWithNameAndType(sequence, name, contentType, revPos, key, length);
1311+
insertAttachmentForSequenceWithNameAndType(sequence, name, contentType, revPos, key, length, encoding, encodedLength);
13031312
} catch (CouchbaseLiteException e) {
13041313
Log.e(Log.TAG_DATABASE, "Attachment information inserstion error: " + name + "=" + attachment.toString(), e);
13051314
return false;
@@ -2854,10 +2863,15 @@ void insertAttachmentForSequence(AttachmentInternal attachment, long sequence) t
28542863
attachment.getName(),
28552864
attachment.getContentType(),
28562865
attachment.getRevpos(),
2857-
attachment.getBlobKey());
2866+
attachment.getBlobKey(),
2867+
attachment.getLength(),
2868+
attachment.getEncoding(),
2869+
attachment.getEncodedLength());
28582870
}
28592871

28602872
/**
2873+
* Note: This method is used only from unit tests.
2874+
*
28612875
* @exclude
28622876
*/
28632877
@InterfaceAudience.Private
@@ -2882,37 +2896,28 @@ public void insertAttachmentForSequenceWithNameAndType(InputStream contentStream
28822896
*/
28832897
@InterfaceAudience.Private
28842898
public void insertAttachmentForSequenceWithNameAndType(long sequence, String name, String contentType, int revpos, BlobKey key) throws CouchbaseLiteException {
2885-
try {
2886-
ContentValues args = new ContentValues();
2887-
args.put("sequence", sequence);
2888-
args.put("filename", name);
2889-
if (key != null) {
2890-
args.put("key", key.getBytes());
2891-
args.put("length", attachments.getSizeOfBlob(key));
2892-
}
2893-
args.put("type", contentType);
2894-
args.put("revpos", revpos);
2895-
long result = database.insert("attachments", null, args);
2896-
if (result == -1) {
2897-
String msg = "Insert attachment failed (returned -1)";
2898-
Log.e(Database.TAG, msg);
2899-
throw new CouchbaseLiteException(msg, Status.INTERNAL_SERVER_ERROR);
2900-
}
2901-
} catch (SQLException e) {
2902-
Log.e(Database.TAG, "Error inserting attachment", e);
2903-
throw new CouchbaseLiteException(e, Status.INTERNAL_SERVER_ERROR);
2904-
}
2899+
insertAttachmentForSequenceWithNameAndType(sequence, name, contentType, revpos, key, key != null ? attachments.getSizeOfBlob(key): -1, AttachmentInternal.AttachmentEncoding.AttachmentEncodingNone, -1);
29052900
}
29062901

2907-
private void insertAttachmentForSequenceWithNameAndType(long sequence, String name, String contentType, int revpos, BlobKey key, long length) throws CouchbaseLiteException {
2902+
private void insertAttachmentForSequenceWithNameAndType(long sequence, String name, String contentType, int revpos, BlobKey key, long length, AttachmentInternal.AttachmentEncoding encoding, long encodedLength) throws CouchbaseLiteException {
29082903
try {
29092904
ContentValues args = new ContentValues();
29102905
args.put("sequence", sequence);
29112906
args.put("filename", name);
2912-
args.put("key", key.getBytes());
2913-
args.put("length", length);
29142907
args.put("type", contentType);
29152908
args.put("revpos", revpos);
2909+
if (key != null) {
2910+
args.put("key", key.getBytes());
2911+
}
2912+
if (length >= 0) {
2913+
args.put("length", length);
2914+
}
2915+
if(encoding == AttachmentInternal.AttachmentEncoding.AttachmentEncodingGZIP) {
2916+
args.put("encoding", encoding.ordinal());
2917+
if (encodedLength >= 0) {
2918+
args.put("encoded_length", encodedLength);
2919+
}
2920+
}
29162921
long result = database.insert("attachments", null, args);
29172922
if (result == -1) {
29182923
String msg = "Insert attachment failed (returned -1)";
@@ -2924,6 +2929,7 @@ private void insertAttachmentForSequenceWithNameAndType(long sequence, String na
29242929
throw new CouchbaseLiteException(e, Status.INTERNAL_SERVER_ERROR);
29252930
}
29262931
}
2932+
29272933
/**
29282934
* @exclude
29292935
*/
@@ -3116,7 +3122,7 @@ public Map<String,Object> getAttachmentsDictForSequenceWithContent(long sequence
31163122

31173123
String args[] = { Long.toString(sequence) };
31183124
try {
3119-
cursor = database.rawQuery("SELECT filename, key, type, length, revpos FROM attachments WHERE sequence=?", args);
3125+
cursor = database.rawQuery("SELECT filename, key, type, encoding, length, encoded_length, revpos FROM attachments WHERE sequence=?", args);
31203126

31213127
if(!cursor.moveToNext()) {
31223128
return null;
@@ -3127,7 +3133,10 @@ public Map<String,Object> getAttachmentsDictForSequenceWithContent(long sequence
31273133
while(!cursor.isAfterLast()) {
31283134

31293135
boolean dataSuppressed = false;
3130-
int length = cursor.getInt(3);
3136+
int length = cursor.getInt(4);
3137+
3138+
AttachmentInternal.AttachmentEncoding encoding = AttachmentInternal.AttachmentEncoding.values()[cursor.getInt(3)];
3139+
int encodedLength = cursor.getInt(5);
31313140

31323141
byte[] keyData = cursor.getBlob(1);
31333142
BlobKey key = new BlobKey(keyData);
@@ -3140,39 +3149,40 @@ public Map<String,Object> getAttachmentsDictForSequenceWithContent(long sequence
31403149
}
31413150
else {
31423151
byte[] data = attachments.blobForKey(key);
3143-
31443152
if(data != null) {
31453153
dataBase64 = Base64.encodeBytes(data); // <-- very expensive
31463154
}
31473155
else {
31483156
Log.w(Database.TAG, "Error loading attachment. Sequence: %s", sequence);
31493157
}
3150-
31513158
}
3159+
}
31523160

3161+
String encodingStr = null;
3162+
if(encoding!=AttachmentInternal.AttachmentEncoding.AttachmentEncodingNone){
3163+
// NOTE: iOS decode if attachment is included int the dict.
3164+
encodingStr = "gzip";
31533165
}
31543166

31553167
Map<String, Object> attachment = new HashMap<String, Object>();
3156-
3157-
3158-
31593168
if(!(dataBase64 != null || dataSuppressed)) {
31603169
attachment.put("stub", true);
31613170
}
3162-
31633171
if(dataBase64 != null) {
31643172
attachment.put("data", dataBase64);
31653173
}
3166-
31673174
if (dataSuppressed == true) {
31683175
attachment.put("follows", true);
31693176
}
3170-
31713177
attachment.put("digest", digestString);
31723178
String contentType = cursor.getString(2);
31733179
attachment.put("content_type", contentType);
3180+
if (encodingStr != null)
3181+
attachment.put("encoding", encodingStr);
31743182
attachment.put("length", length);
3175-
attachment.put("revpos", cursor.getInt(4));
3183+
if (encodingStr != null && encodedLength >= 0)
3184+
attachment.put("encoded_length", encodedLength);
3185+
attachment.put("revpos", cursor.getInt(6));
31763186

31773187
String filename = cursor.getString(0);
31783188
result.put(filename, attachment);
@@ -4262,7 +4272,7 @@ Map<String, AttachmentInternal> getAttachmentsFromRevision(RevisionInternal rev,
42624272
// If there's inline attachment data, decode and store it:
42634273
byte[] newContents;
42644274
try {
4265-
newContents = Base64.decode(newContentBase64);
4275+
newContents = Base64.decode(newContentBase64, Base64.DONT_GUNZIP);
42664276
} catch (IOException e) {
42674277
throw new CouchbaseLiteException(e, Status.BAD_ENCODING);
42684278
}

0 commit comments

Comments
 (0)