本文整理汇总了C#中Couchbase.Lite.Internal.RevisionInternal.MutateAttachments方法的典型用法代码示例。如果您正苦于以下问题:C# RevisionInternal.MutateAttachments方法的具体用法?C# RevisionInternal.MutateAttachments怎么用?C# RevisionInternal.MutateAttachments使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Couchbase.Lite.Internal.RevisionInternal
的用法示例。
在下文中一共展示了RevisionInternal.MutateAttachments方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: ProcessAttachmentsForRevision
internal bool ProcessAttachmentsForRevision(RevisionInternal rev, string prevRevId, Status status)
{
if (status == null) {
status = new Status();
}
status.Code = StatusCode.Ok;
var revAttachments = rev.GetAttachments();
if (revAttachments == null) {
return true; // no-op: no attachments
}
// Deletions can't have attachments:
if (rev.IsDeleted() || revAttachments.Count == 0) {
var body = rev.GetProperties();
body.Remove("_attachments");
rev.SetProperties(body);
return true;
}
int generation = RevisionInternal.GenerationFromRevID(prevRevId) + 1;
IDictionary<string, object> parentAttachments = null;
return rev.MutateAttachments((name, attachInfo) =>
{
AttachmentInternal attachment = null;
try {
attachment = new AttachmentInternal(name, attachInfo);
} catch(CouchbaseLiteException e) {
return null;
}
if(attachment.EncodedContent != null) {
// If there's inline attachment data, decode and store it:
BlobKey blobKey = new BlobKey();
if(!Attachments.StoreBlob(attachment.EncodedContent.ToArray(), blobKey)) {
status.Code = StatusCode.AttachmentError;
return null;
}
attachment.BlobKey = blobKey;
} else if(attachInfo.GetCast<bool>("follows")) {
// "follows" means the uploader provided the attachment in a separate MIME part.
// This means it's already been registered in _pendingAttachmentsByDigest;
// I just need to look it up by its "digest" property and install it into the store:
InstallAttachment(attachment, attachInfo);
} else if(attachInfo.GetCast<bool>("stub")) {
// "stub" on an incoming revision means the attachment is the same as in the parent.
if(parentAttachments == null && prevRevId != null) {
parentAttachments = GetAttachmentsFromDoc(rev.GetDocId(), prevRevId, status);
if(parentAttachments == null) {
if(status.Code == StatusCode.Ok || status.Code == StatusCode.NotFound) {
status.Code = StatusCode.BadAttachment;
}
return null;
}
}
var parentAttachment = parentAttachments == null ? null : parentAttachments.Get(name).AsDictionary<string, object>();
if(parentAttachment == null) {
status.Code = StatusCode.BadAttachment;
return null;
}
return parentAttachment;
}
// Set or validate the revpos:
if(attachment.RevPos == 0) {
attachment.RevPos = generation;
} else if(attachment.RevPos >= generation) {
status.Code = StatusCode.BadAttachment;
return null;
}
Debug.Assert(attachment.IsValid);
return attachment.AsStubDictionary();
});
}
示例2: TransformRevision
internal RevisionInternal TransformRevision(RevisionInternal rev)
{
if (RevisionBodyTransformationFunction != null) {
try {
var generation = rev.GetGeneration();
var xformed = RevisionBodyTransformationFunction(rev);
if (xformed == null) {
return null;
}
if (xformed != rev) {
Debug.Assert((xformed.GetDocId().Equals(rev.GetDocId())));
Debug.Assert((xformed.GetRevId().Equals(rev.GetRevId())));
Debug.Assert((xformed.GetProperties().Get("_revisions").Equals(rev.GetProperties().Get("_revisions"))));
if (xformed.GetProperties().ContainsKey("_attachments")) {
// Insert 'revpos' properties into any attachments added by the callback:
var mx = new RevisionInternal(xformed.GetProperties());
xformed = mx;
mx.MutateAttachments((name, info) =>
{
if (info.Get("revpos") != null) {
return info;
}
if (info.Get("data") == null) {
throw new InvalidOperationException("Transformer added attachment without adding data");
}
var newInfo = new Dictionary<string, object>(info);
newInfo["revpos"] = generation;
return newInfo;
});
}
}
} catch (Exception e) {
Log.W(TAG, String.Format("Exception transforming a revision of doc '{0}'", rev.GetDocId()), e);
}
}
return rev;
}
示例3: StubOutAttachmentsInRevBeforeRevPos
internal static void StubOutAttachmentsInRevBeforeRevPos(RevisionInternal rev, long minRevPos, bool attachmentsFollow)
{
if (minRevPos <= 1 && !attachmentsFollow)
{
return;
}
rev.MutateAttachments((name, attachment) =>
{
var revPos = 0L;
if (attachment.ContainsKey("revpos"))
{
revPos = Convert.ToInt64(attachment["revpos"]);
}
var includeAttachment = (revPos == 0 || revPos >= minRevPos);
var stubItOut = !includeAttachment && (!attachment.ContainsKey("stub") || (bool)attachment["stub"] == false);
var addFollows = includeAttachment && attachmentsFollow && (!attachment.ContainsKey("follows") || (bool)attachment["follows"] == false);
if (!stubItOut && !addFollows)
{
return attachment; // no change
}
// Need to modify attachment entry
var editedAttachment = new Dictionary<string, object>(attachment);
editedAttachment.Remove("data");
if (stubItOut)
{
// ...then remove the 'data' and 'follows' key:
editedAttachment.Remove("follows");
editedAttachment["stub"] = true;
Log.V(TAG, String.Format("Stubbed out attachment {0}: revpos {1} < {2}", rev, revPos, minRevPos));
}
else if (addFollows)
{
editedAttachment.Remove("stub");
editedAttachment["follows"] = true;
Log.V(TAG, String.Format("Added 'follows' for attachment {0}: revpos {1} >= {2}", rev, revPos, minRevPos));
}
return editedAttachment;
});
}
示例4: InlineFollowingAttachmentsIn
// Replaces the "follows" key with the real attachment data in all attachments to 'doc'.
internal bool InlineFollowingAttachmentsIn(RevisionInternal rev)
{
return rev.MutateAttachments((s, attachment)=>
{
if (!attachment.ContainsKey("follows"))
{
return attachment;
}
var fileURL = FileForAttachmentDict(attachment);
byte[] fileData = null;
try
{
var inputStream = fileURL.OpenConnection().GetInputStream();
var os = new ByteArrayOutputStream();
inputStream.CopyTo(os);
fileData = os.ToByteArray();
}
catch (IOException e)
{
Log.E(TAG, "could not retrieve attachment data: {0}".Fmt(fileURL.ToString()), e);
return null;
}
var editedAttachment = new Dictionary<string, object>(attachment);
editedAttachment.Remove("follows");
editedAttachment.Put("data", Convert.ToBase64String(fileData));
return editedAttachment;
});
}
示例5: StubOutAttachmentsInRevBeforeRevPos
// Replaces attachment data whose revpos is < minRevPos with stubs.
// If attachmentsFollow==YES, replaces data with "follows" key.
private static void StubOutAttachmentsInRevBeforeRevPos(RevisionInternal rev, int minRevPos, bool attachmentsFollow)
{
if (minRevPos <= 1 && !attachmentsFollow)
{
return;
}
rev.MutateAttachments((s, attachment)=>
{
var revPos = 0;
if (attachment.Get("revpos") != null)
{
revPos = (int)attachment.Get("revpos");
}
var includeAttachment = (revPos == 0 || revPos >= minRevPos);
var stubItOut = !includeAttachment && (attachment.Get("stub") == null || (bool)attachment.Get("stub") == false);
var addFollows = includeAttachment && attachmentsFollow && (attachment.Get("follows") == null || !(bool)attachment.Get ("follows"));
if (!stubItOut && !addFollows)
{
return attachment;
}
// no change
// Need to modify attachment entry:
var editedAttachment = new Dictionary<string, object>(attachment);
editedAttachment.Remove("data");
if (stubItOut)
{
// ...then remove the 'data' and 'follows' key:
editedAttachment.Remove("follows");
editedAttachment.Put("stub", true);
Log.V(Tag, "Stubbed out attachment {0}: revpos {1} < {2}".Fmt(rev, revPos, minRevPos));
}
else
{
if (addFollows)
{
editedAttachment.Remove("stub");
editedAttachment.Put("follows", true);
Log.V(Tag, "Added 'follows' for attachment {0}: revpos {1} >= {2}".Fmt(rev, revPos, minRevPos));
}
}
return editedAttachment;
});
}
示例6: ExpandAttachments
internal bool ExpandAttachments(RevisionInternal rev, int minRevPos, bool allowFollows,
bool decodeAttachments, Status outStatus)
{
outStatus.Code = StatusCode.Ok;
rev.MutateAttachments((name, attachment) =>
{
var revPos = attachment.GetCast<long>("revpos");
if(revPos < minRevPos && revPos != 0) {
//Stub:
return new Dictionary<string, object> { { "stub", true }, { "revpos", revPos } };
}
var expanded = new Dictionary<string, object>(attachment);
expanded.Remove("stub");
if(decodeAttachments) {
expanded.Remove("encoding");
expanded.Remove("encoded_length");
}
if(allowFollows && SmallestLength(expanded) >= Database.BIG_ATTACHMENT_LENGTH) {
//Data will follow (multipart):
expanded["follows"] = true;
expanded.Remove("data");
} else {
//Put data inline:
expanded.Remove("follows");
Status status = new Status();
var attachObj = AttachmentForDict(attachment, name, status);
if(attachObj == null) {
Log.W(TAG, "Can't get attachment '{0}' of {1} (status {2})", name, rev, status);
outStatus.Code = status.Code;
return attachment;
}
var data = decodeAttachments ? attachObj.Content : attachObj.EncodedContent;
if(data == null) {
Log.W(TAG, "Can't get binary data of attachment '{0}' of {1}", name, rev);
outStatus.Code = StatusCode.NotFound;
return attachment;
}
expanded["data"] = Convert.ToBase64String(data.ToArray());
}
return expanded;
});
return outStatus.Code == StatusCode.Ok;
}
示例7: ProcessAttachmentsForRevision
internal bool ProcessAttachmentsForRevision(RevisionInternal rev, IList<string> ancestry)
{
var revAttachments = rev.GetAttachments();
if (revAttachments == null) {
return true; // no-op: no attachments
}
// Deletions can't have attachments:
if (rev.IsDeleted() || revAttachments.Count == 0) {
var body = rev.GetProperties();
body.Remove("_attachments");
rev.SetProperties(body);
return true;
}
var prevRevId = ancestry != null && ancestry.Count > 0 ? ancestry[0] : null;
int generation = RevisionInternal.GenerationFromRevID(prevRevId) + 1;
IDictionary<string, object> parentAttachments = null;
return rev.MutateAttachments((name, attachInfo) =>
{
AttachmentInternal attachment = null;
try {
attachment = new AttachmentInternal(name, attachInfo);
} catch(CouchbaseLiteException) {
return null;
}
if(attachment.EncodedContent != null) {
// If there's inline attachment data, decode and store it:
BlobKey blobKey = new BlobKey();
if(!Attachments.StoreBlob(attachment.EncodedContent.ToArray(), blobKey)) {
throw new CouchbaseLiteException(
String.Format("Failed to write attachment ' {0}'to disk", name), StatusCode.AttachmentError);
}
attachment.BlobKey = blobKey;
} else if(attachInfo.GetCast<bool>("follows")) {
// "follows" means the uploader provided the attachment in a separate MIME part.
// This means it's already been registered in _pendingAttachmentsByDigest;
// I just need to look it up by its "digest" property and install it into the store:
InstallAttachment(attachment);
} else if(attachInfo.GetCast<bool>("stub")) {
// "stub" on an incoming revision means the attachment is the same as in the parent.
if(parentAttachments == null && prevRevId != null) {
parentAttachments = GetAttachmentsFromDoc(rev.GetDocId(), prevRevId);
if(parentAttachments == null) {
if(Attachments.HasBlobForKey(attachment.BlobKey)) {
// Parent revision's body isn't known (we are probably pulling a rev along
// with its entire history) but it's OK, we have the attachment already
return attachInfo;
}
var ancestorAttachment = FindAttachment(name, attachment.RevPos, rev.GetDocId(), ancestry);
if(ancestorAttachment != null) {
return ancestorAttachment;
}
throw new CouchbaseLiteException(
String.Format("Unable to find 'stub' attachment {0} in history", name), StatusCode.BadAttachment);
}
}
var parentAttachment = parentAttachments == null ? null : parentAttachments.Get(name).AsDictionary<string, object>();
if(parentAttachment == null) {
throw new CouchbaseLiteException(
String.Format("Unable to find 'stub' attachment {0} in history", name), StatusCode.BadAttachment);
}
return parentAttachment;
}
// Set or validate the revpos:
if(attachment.RevPos == 0) {
attachment.RevPos = generation;
} else if(attachment.RevPos > generation) {
throw new CouchbaseLiteException(
String.Format("Attachment specifies revision generation {0} but document is only at revision generation {1}",
attachment.RevPos, generation), StatusCode.BadAttachment);
}
Debug.Assert(attachment.IsValid);
return attachment.AsStubDictionary();
});
}
示例8: ExpandAttachments
internal void ExpandAttachments(RevisionInternal rev, int minRevPos, bool allowFollows,
bool decodeAttachments)
{
if (!IsOpen) {
throw new CouchbaseLiteException("DB is closed", StatusCode.DbError);
}
rev.MutateAttachments((name, attachment) =>
{
var revPos = attachment.GetCast<long>("revpos");
if(revPos < minRevPos && revPos != 0) {
//Stub:
return new Dictionary<string, object> { { "stub", true }, { "revpos", revPos } };
}
var expanded = new Dictionary<string, object>(attachment);
expanded.Remove("stub");
if(decodeAttachments) {
expanded.Remove("encoding");
expanded.Remove("encoded_length");
}
if(allowFollows && SmallestLength(expanded) >= Database.BIG_ATTACHMENT_LENGTH) {
//Data will follow (multipart):
expanded["follows"] = true;
expanded.Remove("data");
} else {
//Put data inline:
expanded.Remove("follows");
var attachObj = AttachmentForDict(attachment, name);
var data = decodeAttachments ? attachObj.Content : attachObj.EncodedContent;
if(data == null) {
Log.W(TAG, "Can't get binary data of attachment '{0}' of {1}", name, rev);
return attachment;
}
expanded["data"] = Convert.ToBase64String(data.ToArray());
}
return expanded;
});
}
示例9: TransformRevision
internal RevisionInternal TransformRevision(RevisionInternal rev)
{
if (RevisionBodyTransformationFunction != null) {
try {
var generation = rev.Generation;
var xformed = RevisionBodyTransformationFunction(rev);
if (xformed == null) {
return null;
}
if (xformed != rev) {
Debug.Assert((xformed.DocID.Equals(rev.DocID)));
Debug.Assert((xformed.RevID.Equals(rev.RevID)));
Debug.Assert((xformed.GetProperties().Get("_revisions").Equals(rev.GetProperties().Get("_revisions"))));
if (xformed.GetProperties().ContainsKey("_attachments")) {
// Insert 'revpos' properties into any attachments added by the callback:
var mx = new RevisionInternal(xformed.GetProperties());
xformed = mx;
mx.MutateAttachments((name, info) =>
{
if (info.Get("revpos") != null) {
return info;
}
if (info.Get("data") == null) {
throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.InternalServerError, Tag,
"Transformer added attachment without adding data");
}
var newInfo = new Dictionary<string, object>(info);
newInfo["revpos"] = generation;
return newInfo;
});
}
}
} catch (Exception e) {
Log.To.Sync.W(Tag, String.Format("Exception transforming a revision of doc '{0}', aborting...",
new SecureLogString(rev.DocID, LogMessageSensitivity.PotentiallyInsecure)), e);
}
}
return rev;
}
示例10: ProcessAttachmentsForRevision
internal bool ProcessAttachmentsForRevision(RevisionInternal rev, IList<RevisionID> ancestry)
{
var revAttachments = rev.GetAttachments();
if(revAttachments == null) {
return true; // no-op: no attachments
}
// Deletions can't have attachments:
if(rev.Deleted || revAttachments.Count == 0) {
var body = rev.GetProperties();
body.Remove("_attachments");
rev.SetProperties(body);
return true;
}
var prevRevId = ancestry != null && ancestry.Count > 0 ? ancestry[0] : null;
int generation = rev.Generation;
IDictionary<string, object> parentAttachments = null;
return rev.MutateAttachments((name, attachInfo) =>
{
AttachmentInternal attachment = null;
try {
attachment = new AttachmentInternal(name, attachInfo);
} catch(CouchbaseLiteException) {
Log.To.Database.W(TAG, "Error creating attachment object for '{0}' ('{1}'), " +
"returning null", new SecureLogString(name, LogMessageSensitivity.PotentiallyInsecure),
new SecureLogJsonString(attachInfo, LogMessageSensitivity.PotentiallyInsecure));
return null;
}
if(attachment.EncodedContent != null) {
// If there's inline attachment data, decode and store it:
BlobKey blobKey = new BlobKey();
try {
Attachments.StoreBlob(attachment.EncodedContent.ToArray(), blobKey);
} catch(CouchbaseLiteException) {
Log.To.Database.E(TAG, "Failed to write attachment '{0}' to disk, rethrowing...", name);
throw;
} catch(Exception e) {
throw Misc.CreateExceptionAndLog(Log.To.Database, e, TAG,
"Exception during attachment writing '{0}'",
new SecureLogString(name, LogMessageSensitivity.PotentiallyInsecure));
}
attachment.BlobKey = blobKey;
} else if(attachInfo.GetCast<bool>("follows")) {
// "follows" means the uploader provided the attachment in a separate MIME part.
// This means it's already been registered in _pendingAttachmentsByDigest;
// I just need to look it up by its "digest" property and install it into the store:
InstallAttachment(attachment);
} else if(attachInfo.GetCast<bool>("stub")) {
// "stub" on an incoming revision means the attachment is the same as in the parent.
if(parentAttachments == null && prevRevId != null) {
parentAttachments = GetAttachmentsFromDoc(rev.DocID, prevRevId);
if(parentAttachments == null) {
if(Attachments.HasBlobForKey(attachment.BlobKey)) {
// Parent revision's body isn't known (we are probably pulling a rev along
// with its entire history) but it's OK, we have the attachment already
return attachInfo;
}
var ancestorAttachment = FindAttachment(name, attachment.RevPos, rev.DocID, ancestry);
if(ancestorAttachment != null) {
return ancestorAttachment;
}
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadAttachment, TAG,
"Unable to find 'stub' attachment {0} in history (1)",
new SecureLogString(name, LogMessageSensitivity.PotentiallyInsecure));
}
}
var parentAttachment = parentAttachments == null ? null : parentAttachments.Get(name).AsDictionary<string, object>();
if(parentAttachment == null) {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadAttachment, TAG,
"Unable to find 'stub' attachment {0} in history (2)",
new SecureLogString(name, LogMessageSensitivity.PotentiallyInsecure));
}
return parentAttachment;
}
// Set or validate the revpos:
if(attachment.RevPos == 0) {
attachment.RevPos = generation;
} else if(attachment.RevPos > generation) {
throw Misc.CreateExceptionAndLog(Log.To.Database, StatusCode.BadAttachment, TAG,
"Attachment specifies revision generation {0} but document is only at revision generation {1}",
attachment.RevPos, generation);
}
Debug.Assert(attachment.IsValid);
return attachment.AsStubDictionary();
});
}
示例11: RegisterAttachmentBodies
internal bool RegisterAttachmentBodies(IDictionary<string, Stream> attachments, RevisionInternal rev)
{
var ok = true;
rev.MutateAttachments((name, meta) =>
{
var value = attachments.Get(name);
if(value != null) {
// Register attachment body with database
var writer = AttachmentWriter;
try {
writer.Read(value);
writer.Finish();
} catch(Exception e) {
Log.To.Database.W(TAG, $"Error reading stream for attachment {name}, skipping...",
e);
ok = false;
return null;
}
// Make attachment mode "follows", indicating the data is registered
var nuMeta = new Dictionary<string, object>(meta);
nuMeta.Remove("data");
nuMeta.Remove("stub");
nuMeta["follows"] = true;
// Add or verify metadata "digest" property
var digest = meta.GetCast<string>("digest");
var sha1Digest = writer.SHA1DigestString();
if(digest != null) {
if(digest != sha1Digest && digest != writer.MD5DigestString()) {
Log.To.Database.W(TAG, "Attachment '{0}' body digest ({1}) doesn't match " +
"'digest' property {2}", name, sha1Digest, digest);
ok = false;
return null;
}
} else {
nuMeta["digest"] = digest = sha1Digest;
}
RememberAttachmentWriter(writer, digest);
return nuMeta;
}
return meta;
});
return ok;
}