public override void Process() { Remoting.Get rem; TriggerOnActionChanged(EngineActionType.GettingVersion, true); try { rem = new Remoting.Get(_db, _id.ToString(), _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize); } catch (Exception e) { Logger.Storage.Error("An exception occurred while instantiating the Transactions.Tasks.Remoting.Get object.", e); throw; } rem.OnComplete += delegate(Remoting.Base sender, ICommandReply reply) { JObject jobj; Transitions.Version txVersion = new Transitions.Version(); Version = txVersion.Transition(((Remoting.Get)sender).Document, out jobj); Remainder = jobj; TriggerOnComplete(reply); }; rem.OnError += delegate(Remoting.Base sender, string message, Exception exception) { TriggerOnError(message, exception); }; rem.OnProgress += delegate(Remoting.Base sender, OpenDMS.Networking.Protocols.Tcp.DirectionType direction, int packetSize, decimal sendPercentComplete, decimal receivePercentComplete) { TriggerOnProgress(direction, packetSize, sendPercentComplete, receivePercentComplete); }; rem.OnTimeout += delegate(Remoting.Base sender) { TriggerOnTimeout(); }; rem.Process(); }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { Type t = sender.GetType(); if (t == typeof(Tasks.DownloadResource)) { Tasks.DownloadResource task = (Tasks.DownloadResource)sender; _resource = task.Resource; _resourceRemainder = task.Remainder; RunTaskProcess(new Tasks.CheckResourcePermissions(_db, _resource, _requestingPartyType, _session, Security.Authorization.ResourcePermissionType.Modify, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckResourcePermissions)) { Tasks.CheckResourcePermissions task = (Tasks.CheckResourcePermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } RunTaskProcess(new Tasks.MarkResourceForCheckout(_resource, _session.User.Username, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.MarkResourceForCheckout)) { Tasks.MarkResourceForCheckout task = (Tasks.MarkResourceForCheckout)sender; _resource = task.Resource; List<Exception> errors; List<Model.Document> docs = new List<Model.Document>(); Transitions.Version txVersion = new Transitions.Version(); Transitions.Resource txResource = new Transitions.Resource(); docs.Add(txResource.Transition(_resource, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } docs[0].CombineWith(_resourceRemainder); docs.Add(txVersion.Transition(_version, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; Commands.PostBulkDocumentsReply.Entry entry = task.FindEntryById(_version.VersionId.ToString()); if (entry == null) { TriggerOnError(task, "Failed to locate " + _version.VersionId.ToString() + " in the " + "bulk document post results.", null); return; } // This is needed so that couchdb can apply the content to the correct revision. _version.UpdateRevision(entry.Rev); // If no content -> return if (_version.Content == null) { Resource = _resource; Version = _version; TriggerOnComplete(reply, new Tuple<Data.Resource, Data.Version>(_resource, _version)); return; } // Upload Data.Content from Data.Version RunTaskProcess(new Tasks.UploadContent(_db, _version, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadContent)) { Resource = _resource; Version = _version; TriggerOnComplete(reply, new Tuple<Data.Resource, Data.Version>(_resource, _version)); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void Process() { Commands.PutAttachment cmd; List<Exception> errors; OpenDMS.IO.FileStream stream; Transitions.Version txVersion = new Transitions.Version(); Model.Document doc = txVersion.Transition(_version, out errors); if (errors != null) { TriggerOnError(errors[0].Message, errors[0]); return; } if (doc.Attachments == null || doc.Attachments.Count == 0) { TriggerOnError("No content to upload.", null); return; } else if(doc.Attachments.Count > 1) { TriggerOnError("To many content elements found, only one is expected.", null); return; } Dictionary<string, Model.Attachment>.Enumerator en = doc.Attachments.GetEnumerator(); // Due to the above checks, we know there is 1 and only 1 entry en.MoveNext(); stream = GetStream(); if (stream == null) { TriggerOnError("Could not access a content stream.", null); return; } try { cmd = new Commands.PutAttachment(_db, doc, en.Current.Key, en.Current.Value, stream); } catch (Exception e) { Logger.Storage.Error("An exception occurred while creating the PutDocument command.", e); throw; } cmd.OnComplete += delegate(Commands.Base sender, Http.Client client, Http.HttpConnection connection, Commands.ReplyBase reply) { stream.Close(); stream.Dispose(); TriggerOnComplete(reply); }; cmd.OnError += delegate(Commands.Base sender, Http.Client client, string message, Exception exception) { TriggerOnError(message, exception); stream.Close(); stream.Dispose(); }; cmd.OnProgress += delegate(Commands.Base sender, Http.Client client, Http.HttpConnection connection, Tcp.DirectionType direction, int packetSize, decimal sendPercentComplete, decimal receivePercentComplete) { TriggerOnProgress(direction, packetSize, sendPercentComplete, receivePercentComplete); }; cmd.OnTimeout += delegate(Commands.Base sender, Http.Client client, Http.HttpConnection connection) { TriggerOnTimeout(); }; cmd.Execute(_sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize); }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { Type t = sender.GetType(); if (t == typeof(Tasks.DownloadResource)) { Tasks.DownloadResource task = (Tasks.DownloadResource)sender; _resource = task.Resource; _resourceRemainder = task.Remainder; RunTaskProcess(new Tasks.CheckResourcePermissions(_db, _resource, _requestingPartyType, _session, Security.Authorization.ResourcePermissionType.Modify, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckResourcePermissions)) { Tasks.CheckResourcePermissions task = (Tasks.CheckResourcePermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } RunTaskProcess(new Tasks.MarkResourceForCheckout(_resource, _session.User.Username, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.MarkResourceForCheckout)) { Tasks.MarkResourceForCheckout task = (Tasks.MarkResourceForCheckout)sender; _resource = task.Resource; List <Exception> errors; List <Model.Document> docs = new List <Model.Document>(); Transitions.Version txVersion = new Transitions.Version(); Transitions.Resource txResource = new Transitions.Resource(); docs.Add(txResource.Transition(_resource, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } docs[0].CombineWith(_resourceRemainder); docs.Add(txVersion.Transition(_version, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; Commands.PostBulkDocumentsReply.Entry entry = task.FindEntryById(_version.VersionId.ToString()); if (entry == null) { TriggerOnError(task, "Failed to locate " + _version.VersionId.ToString() + " in the " + "bulk document post results.", null); return; } // This is needed so that couchdb can apply the content to the correct revision. _version.UpdateRevision(entry.Rev); // If no content -> return if (_version.Content == null) { Resource = _resource; Version = _version; TriggerOnComplete(reply, new Tuple <Data.Resource, Data.Version>(_resource, _version)); return; } // Upload Data.Content from Data.Version RunTaskProcess(new Tasks.UploadContent(_db, _version, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadContent)) { Resource = _resource; Version = _version; TriggerOnComplete(reply, new Tuple <Data.Resource, Data.Version>(_resource, _version)); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { Type t = sender.GetType(); if (t == typeof(Tasks.DownloadResource)) { Tasks.DownloadResource task = (Tasks.DownloadResource)sender; _resource = task.Resource; _remainder = task.Remainder; RunTaskProcess(new Tasks.CheckResourcePermissions(_db, _resource, _requestingPartyType, _session, Security.Authorization.ResourcePermissionType.Delete, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckResourcePermissions)) { Tasks.CheckResourcePermissions task = (Tasks.CheckResourcePermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } // First, we load up revisions for (int i = 0; i < _resource.VersionIds.Count; i++) { _versions.Add(_resource.VersionIds[i], new Data.Version(_resource.VersionIds[i])); } // Now our _revisions holds indexes for all version ids // Dispatch all our heads to get the revisions // *note* do not combine these loops - we want the full dictionary before starting for (int i = 0; i < _resource.VersionIds.Count; i++) { RunTaskProcess(new Tasks.HeadVersion(_db, _resource.VersionIds[i], _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } } else if (t == typeof(Tasks.HeadVersion)) { Tasks.HeadVersion task = (Tasks.HeadVersion)sender; if (!_versions.ContainsKey(task.VersionId)) { TriggerOnError(task, "The id '" + task.VersionId.ToString() + "' could not be found.", new KeyNotFoundException()); return; } lock (_versions) { _receivedCount++; _versions[task.VersionId].UpdateRevision(task.Revision); if (_versions.Count == _receivedCount) { List <Exception> errors; List <Model.Document> docs = new List <Model.Document>(); Transitions.Resource txResource = new Transitions.Resource(); Model.Document doc = txResource.Transition(_resource, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } // Pointless, we are deleting it //doc.CombineWith(_remainder); doc.Add("_deleted", true); docs.Add(doc); Dictionary <Data.VersionId, Data.Version> .Enumerator en = _versions.GetEnumerator(); while (en.MoveNext()) { Transitions.Version txVersion = new Transitions.Version(); Model.Document doc2 = txVersion.Transition(en.Current.Value, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } doc2.Add("_deleted", true); docs.Add(doc2); } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else { TriggerOnProgress(task, Networking.Protocols.Tcp.DirectionType.Download, -1, -1, ((decimal)((decimal)_receivedCount / (decimal)_versions.Count))); } } } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; TriggerOnComplete(reply, task.Results); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { Type t = sender.GetType(); if (t == typeof(Tasks.DownloadGlobalPermissions)) { Tasks.DownloadGlobalPermissions task = (Tasks.DownloadGlobalPermissions)sender; _gur = task.GlobalUsageRights; RunTaskProcess(new Tasks.CheckGlobalPermissions(_db, _gur, _requestingPartyType, _session, Security.Authorization.GlobalPermissionType.CreateResource, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckGlobalPermissions)) { Tasks.CheckGlobalPermissions task = (Tasks.CheckGlobalPermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } RunTaskProcess(new Tasks.DownloadResourceUsageRightsTemplate(_db, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.DownloadResourceUsageRightsTemplate)) { string username = _session.User.Username; DateTime creation = DateTime.Now; List<Exception> errors; List<Model.Document> docs = new List<Model.Document>(); Tasks.DownloadResourceUsageRightsTemplate task = (Tasks.DownloadResourceUsageRightsTemplate)sender; // Create the Resource and Version objects List<Data.VersionId> versions = new List<Data.VersionId>(); Data.ResourceId resourceId = Data.ResourceId.Create(); _version = new Data.Version(new Data.VersionId(resourceId), _args.VersionArgs.Metadata, _args.VersionArgs.Content) { Md5 = _args.VersionArgs.Md5, Extension = _args.VersionArgs.Extension, Created = creation, Creator = username, Modified = creation, Modifier = username }; versions.Add(_version.VersionId); _resource = new Data.Resource(resourceId, null, versions, _version.VersionId, _args.Metadata, task.Value.UsageRights) { Tags = _args.Tags, Created = creation, Creator = username, Modified = creation, Modifier = username, CheckedOutAt = creation, CheckedOutTo = username, LastCommit = creation, LastCommitter = username, Title = _args.Title }; // Transition to json objects Transitions.Resource txResource = new Transitions.Resource(); docs.Add(txResource.Transition(_resource, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } Transitions.Version txVersion = new Transitions.Version(); docs.Add(txVersion.Transition(_version, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; Commands.PostBulkDocumentsReply.Entry entry = task.FindEntryById(_version.VersionId.ToString()); if (entry == null) { TriggerOnError(task, "Failed to locate " + _version.VersionId.ToString() + " in the " + "bulk document post results.", null); return; } // This is needed so that couchdb can apply the content to the correct revision. _version.UpdateRevision(entry.Rev); // Upload Data.Content from Data.Version RunTaskProcess(new Tasks.UploadContent(_db, _version, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadContent)) { TriggerOnComplete(reply, new Tuple<Data.Resource, Data.Version>(_resource, _version)); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { Type t = sender.GetType(); if (t == typeof(Tasks.DownloadResource)) { Tasks.DownloadResource task = (Tasks.DownloadResource)sender; _resource = task.Resource; _remainder = task.Remainder; RunTaskProcess(new Tasks.CheckResourcePermissions(_db, _resource, _requestingPartyType, _session, Security.Authorization.ResourcePermissionType.Delete, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckResourcePermissions)) { Tasks.CheckResourcePermissions task = (Tasks.CheckResourcePermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } // First, we load up revisions for (int i = 0; i < _resource.VersionIds.Count; i++) { _versions.Add(_resource.VersionIds[i], new Data.Version(_resource.VersionIds[i])); } // Now our _revisions holds indexes for all version ids // Dispatch all our heads to get the revisions // *note* do not combine these loops - we want the full dictionary before starting for (int i = 0; i < _resource.VersionIds.Count; i++) { RunTaskProcess(new Tasks.HeadVersion(_db, _resource.VersionIds[i], _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } } else if (t == typeof(Tasks.HeadVersion)) { Tasks.HeadVersion task = (Tasks.HeadVersion)sender; if (!_versions.ContainsKey(task.VersionId)) { TriggerOnError(task, "The id '" + task.VersionId.ToString() + "' could not be found.", new KeyNotFoundException()); return; } lock (_versions) { _receivedCount++; _versions[task.VersionId].UpdateRevision(task.Revision); if (_versions.Count == _receivedCount) { List<Exception> errors; List<Model.Document> docs = new List<Model.Document>(); Transitions.Resource txResource = new Transitions.Resource(); Model.Document doc = txResource.Transition(_resource, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } // Pointless, we are deleting it //doc.CombineWith(_remainder); doc.Add("_deleted", true); docs.Add(doc); Dictionary<Data.VersionId, Data.Version>.Enumerator en = _versions.GetEnumerator(); while (en.MoveNext()) { Transitions.Version txVersion = new Transitions.Version(); Model.Document doc2 = txVersion.Transition(en.Current.Value, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } doc2.Add("_deleted", true); docs.Add(doc2); } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else { TriggerOnProgress(task, Networking.Protocols.Tcp.DirectionType.Download, -1, -1, ((decimal)((decimal)_receivedCount / (decimal)_versions.Count))); } } } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; TriggerOnComplete(reply, task.Results); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void Process() { Commands.PutAttachment cmd; List <Exception> errors; OpenDMS.IO.FileStream stream; Transitions.Version txVersion = new Transitions.Version(); Model.Document doc = txVersion.Transition(_version, out errors); if (errors != null) { TriggerOnError(errors[0].Message, errors[0]); return; } if (doc.Attachments == null || doc.Attachments.Count == 0) { TriggerOnError("No content to upload.", null); return; } else if (doc.Attachments.Count > 1) { TriggerOnError("To many content elements found, only one is expected.", null); return; } Dictionary <string, Model.Attachment> .Enumerator en = doc.Attachments.GetEnumerator(); // Due to the above checks, we know there is 1 and only 1 entry en.MoveNext(); stream = GetStream(); if (stream == null) { TriggerOnError("Could not access a content stream.", null); return; } try { cmd = new Commands.PutAttachment(_db, doc, en.Current.Key, en.Current.Value, stream); } catch (Exception e) { Logger.Storage.Error("An exception occurred while creating the PutDocument command.", e); throw; } cmd.OnComplete += delegate(Commands.Base sender, Http.Client client, Http.HttpConnection connection, Commands.ReplyBase reply) { stream.Close(); stream.Dispose(); TriggerOnComplete(reply); }; cmd.OnError += delegate(Commands.Base sender, Http.Client client, string message, Exception exception) { TriggerOnError(message, exception); stream.Close(); stream.Dispose(); }; cmd.OnProgress += delegate(Commands.Base sender, Http.Client client, Http.HttpConnection connection, Tcp.DirectionType direction, int packetSize, decimal sendPercentComplete, decimal receivePercentComplete) { TriggerOnProgress(direction, packetSize, sendPercentComplete, receivePercentComplete); }; cmd.OnTimeout += delegate(Commands.Base sender, Http.Client client, Http.HttpConnection connection) { TriggerOnTimeout(); }; cmd.Execute(_sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize); }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { /* We encounter a bit of an issue here. Upon doing some research it is easily resolved * by couchdb. Lets examine. * * Issue: We update the resource to the server, connection is lost, we try to delete the * versions newer than the target version of the rollback. This fails. We now have * zombie versions that will block future recreation of those versions as the IDs will * be the same. * * Solution: "Updating existing documents requires setting the _rev member to the * revision being updated. To delete a document set the _deleted member to true." * http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API. * * Example: * { * "docs": [ * {"_id": "0", "_rev": "1-62657917", "_deleted": true}, * {"_id": "1", "_rev": "1-2089673485", "integer": 2, "string": "2"}, * {"_id": "2", "_rev": "1-2063452834", "integer": 3, "string": "3"} * ] * } * * Implementation: So, we already have bulk document post support. We simply need to * load the bulkdocument with the resource and the _id and _rev for each version we want * to remove. We will also want to set the _deleted to true. */ // 1) Download Resource // 2) Check for VersionControl permission // 3) Modify Resource (VersionIds, CurrentVersionId) // 4) Make bulk document // 5) Upload bulk document Type t = sender.GetType(); if (t == typeof(Tasks.DownloadResource)) { Tasks.DownloadResource task = (Tasks.DownloadResource)sender; _resource = task.Resource; _remainder = task.Remainder; RunTaskProcess(new Tasks.CheckResourcePermissions(_db, _resource, _requestingPartyType, _session, Security.Authorization.ResourcePermissionType.VersionControl, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckResourcePermissions)) { Data.VersionId oldCurrentVersionId; Tasks.CheckResourcePermissions task = (Tasks.CheckResourcePermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } // If version number < rollback -> error // Versions: 0,1,2 / rollback: 2 -> 0th version if (_resource.CurrentVersionId.VersionNumber < _rollbackDepth) { TriggerOnError(null, "Rollback depth out of range.", null); return; } else if (_rollbackDepth <= 0) { TriggerOnError(null, "Rollback depth must be a positive value.", null); return; } oldCurrentVersionId = _resource.CurrentVersionId; _versionsToDelete = new Dictionary<Data.VersionId, Data.Version>(); long targetVersionNumber = _resource.CurrentVersionId.VersionNumber - _rollbackDepth; for(int i=0; i<_resource.VersionIds.Count; i++) { if (_resource.VersionIds[i].VersionNumber > targetVersionNumber) { Data.VersionId vid = new Data.VersionId(_resource.ResourceId, i); _versionsToDelete.Add(vid, new Data.Version(vid)); } } // Removes the versions more recent than the rollback point _resource.VersionIds.RemoveRange(_resource.VersionIds.Count - _rollbackDepth, _rollbackDepth); _resource.UpdateCurrentVersionBasedOnVersionsList(); Dictionary<Data.VersionId, Data.Version>.Enumerator en = _versionsToDelete.GetEnumerator(); // Dispatch all our heads to get the revisions // *note* do not combine these loops - we want the full list before starting while (en.MoveNext()) { RunTaskProcess(new Tasks.HeadVersion(_db, en.Current.Key, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } } else if (t == typeof(Tasks.HeadVersion)) { Tasks.HeadVersion task = (Tasks.HeadVersion)sender; if (!_versionsToDelete.ContainsKey(task.VersionId)) { TriggerOnError(task, "The id '" + task.VersionId.ToString() + "' could not be found.", new KeyNotFoundException()); return; } lock (_versionsToDelete) { _receivedCount++; _versionsToDelete[task.VersionId].UpdateRevision(task.Revision); if (_versionsToDelete.Count == _receivedCount) { // Inside here we have a collection "docs" that contains the new resource // which has the new "current" version and has all the more recent // versions removed. We also have inside "docs" deletion markers for all // the more recent versions. List<Exception> errors; List<Model.Document> docs = new List<Model.Document>(); Transitions.Resource txResource = new Transitions.Resource(); Model.Document doc = txResource.Transition(_resource, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } doc.CombineWith(_remainder); docs.Add(doc); Dictionary<Data.VersionId, Data.Version>.Enumerator en = _versionsToDelete.GetEnumerator(); // Dispatch all our heads to get the revisions // *note* do not combine these loops - we want the full list before starting while (en.MoveNext()) { Transitions.Version txVersion = new Transitions.Version(); Model.Document doc2 = txVersion.Transition(en.Current.Value, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } doc2.Add("_deleted", true); docs.Add(doc2); } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } } } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; TriggerOnComplete(reply, task.Results); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { /* We encounter a bit of an issue here. Upon doing some research it is easily resolved * by couchdb. Lets examine. * * Issue: We update the resource to the server, connection is lost, we try to delete the * versions newer than the target version of the rollback. This fails. We now have * zombie versions that will block future recreation of those versions as the IDs will * be the same. * * Solution: "Updating existing documents requires setting the _rev member to the * revision being updated. To delete a document set the _deleted member to true." * http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API. * * Example: * { * "docs": [ * {"_id": "0", "_rev": "1-62657917", "_deleted": true}, * {"_id": "1", "_rev": "1-2089673485", "integer": 2, "string": "2"}, * {"_id": "2", "_rev": "1-2063452834", "integer": 3, "string": "3"} * ] * } * * Implementation: So, we already have bulk document post support. We simply need to * load the bulkdocument with the resource and the _id and _rev for each version we want * to remove. We will also want to set the _deleted to true. */ // 1) Download Resource // 2) Check for VersionControl permission // 3) Modify Resource (VersionIds, CurrentVersionId) // 4) Make bulk document // 5) Upload bulk document Type t = sender.GetType(); if (t == typeof(Tasks.DownloadResource)) { Tasks.DownloadResource task = (Tasks.DownloadResource)sender; _resource = task.Resource; _remainder = task.Remainder; RunTaskProcess(new Tasks.CheckResourcePermissions(_db, _resource, _requestingPartyType, _session, Security.Authorization.ResourcePermissionType.VersionControl, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckResourcePermissions)) { Data.VersionId oldCurrentVersionId; Tasks.CheckResourcePermissions task = (Tasks.CheckResourcePermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } // If version number < rollback -> error // Versions: 0,1,2 / rollback: 2 -> 0th version if (_resource.CurrentVersionId.VersionNumber < _rollbackDepth) { TriggerOnError(null, "Rollback depth out of range.", null); return; } else if (_rollbackDepth <= 0) { TriggerOnError(null, "Rollback depth must be a positive value.", null); return; } oldCurrentVersionId = _resource.CurrentVersionId; _versionsToDelete = new Dictionary <Data.VersionId, Data.Version>(); long targetVersionNumber = _resource.CurrentVersionId.VersionNumber - _rollbackDepth; for (int i = 0; i < _resource.VersionIds.Count; i++) { if (_resource.VersionIds[i].VersionNumber > targetVersionNumber) { Data.VersionId vid = new Data.VersionId(_resource.ResourceId, i); _versionsToDelete.Add(vid, new Data.Version(vid)); } } // Removes the versions more recent than the rollback point _resource.VersionIds.RemoveRange(_resource.VersionIds.Count - _rollbackDepth, _rollbackDepth); _resource.UpdateCurrentVersionBasedOnVersionsList(); Dictionary <Data.VersionId, Data.Version> .Enumerator en = _versionsToDelete.GetEnumerator(); // Dispatch all our heads to get the revisions // *note* do not combine these loops - we want the full list before starting while (en.MoveNext()) { RunTaskProcess(new Tasks.HeadVersion(_db, en.Current.Key, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } } else if (t == typeof(Tasks.HeadVersion)) { Tasks.HeadVersion task = (Tasks.HeadVersion)sender; if (!_versionsToDelete.ContainsKey(task.VersionId)) { TriggerOnError(task, "The id '" + task.VersionId.ToString() + "' could not be found.", new KeyNotFoundException()); return; } lock (_versionsToDelete) { _receivedCount++; _versionsToDelete[task.VersionId].UpdateRevision(task.Revision); if (_versionsToDelete.Count == _receivedCount) { // Inside here we have a collection "docs" that contains the new resource // which has the new "current" version and has all the more recent // versions removed. We also have inside "docs" deletion markers for all // the more recent versions. List <Exception> errors; List <Model.Document> docs = new List <Model.Document>(); Transitions.Resource txResource = new Transitions.Resource(); Model.Document doc = txResource.Transition(_resource, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } doc.CombineWith(_remainder); docs.Add(doc); Dictionary <Data.VersionId, Data.Version> .Enumerator en = _versionsToDelete.GetEnumerator(); // Dispatch all our heads to get the revisions // *note* do not combine these loops - we want the full list before starting while (en.MoveNext()) { Transitions.Version txVersion = new Transitions.Version(); Model.Document doc2 = txVersion.Transition(en.Current.Value, out errors); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } doc2.Add("_deleted", true); docs.Add(doc2); } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } } } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; TriggerOnComplete(reply, task.Results); } else { TriggerOnError(sender, reply.ToString(), null); } }
public override void TaskComplete(Tasks.Base sender, ICommandReply reply) { Type t = sender.GetType(); if (t == typeof(Tasks.DownloadGlobalPermissions)) { Tasks.DownloadGlobalPermissions task = (Tasks.DownloadGlobalPermissions)sender; _gur = task.GlobalUsageRights; RunTaskProcess(new Tasks.CheckGlobalPermissions(_db, _gur, _requestingPartyType, _session, Security.Authorization.GlobalPermissionType.CreateResource, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.CheckGlobalPermissions)) { Tasks.CheckGlobalPermissions task = (Tasks.CheckGlobalPermissions)sender; if (!task.IsAuthorized) { TriggerOnAuthorizationDenied(task); return; } RunTaskProcess(new Tasks.DownloadResourceUsageRightsTemplate(_db, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.DownloadResourceUsageRightsTemplate)) { string username = _session.User.Username; DateTime creation = DateTime.Now; List <Exception> errors; List <Model.Document> docs = new List <Model.Document>(); Tasks.DownloadResourceUsageRightsTemplate task = (Tasks.DownloadResourceUsageRightsTemplate)sender; // Create the Resource and Version objects List <Data.VersionId> versions = new List <Data.VersionId>(); Data.ResourceId resourceId = Data.ResourceId.Create(); _version = new Data.Version(new Data.VersionId(resourceId), _args.VersionArgs.Metadata, _args.VersionArgs.Content) { Md5 = _args.VersionArgs.Md5, Extension = _args.VersionArgs.Extension, Created = creation, Creator = username, Modified = creation, Modifier = username }; versions.Add(_version.VersionId); _resource = new Data.Resource(resourceId, null, versions, _version.VersionId, _args.Metadata, task.Value.UsageRights) { Tags = _args.Tags, Created = creation, Creator = username, Modified = creation, Modifier = username, CheckedOutAt = creation, CheckedOutTo = username, LastCommit = creation, LastCommitter = username, Title = _args.Title }; // Transition to json objects Transitions.Resource txResource = new Transitions.Resource(); docs.Add(txResource.Transition(_resource, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } Transitions.Version txVersion = new Transitions.Version(); docs.Add(txVersion.Transition(_version, out errors)); if (errors != null) { TriggerOnError(null, errors[0].Message, errors[0]); return; } RunTaskProcess(new Tasks.MakeBulkDocument(docs, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.MakeBulkDocument)) { Tasks.MakeBulkDocument task = (Tasks.MakeBulkDocument)sender; RunTaskProcess(new Tasks.UploadBulkDocuments(_db, task.BulkDocument, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadBulkDocuments)) { Tasks.UploadBulkDocuments task = (Tasks.UploadBulkDocuments)sender; Commands.PostBulkDocumentsReply.Entry entry = task.FindEntryById(_version.VersionId.ToString()); if (entry == null) { TriggerOnError(task, "Failed to locate " + _version.VersionId.ToString() + " in the " + "bulk document post results.", null); return; } // This is needed so that couchdb can apply the content to the correct revision. _version.UpdateRevision(entry.Rev); // Upload Data.Content from Data.Version RunTaskProcess(new Tasks.UploadContent(_db, _version, _sendTimeout, _receiveTimeout, _sendBufferSize, _receiveBufferSize)); } else if (t == typeof(Tasks.UploadContent)) { TriggerOnComplete(reply, new Tuple <Data.Resource, Data.Version>(_resource, _version)); } else { TriggerOnError(sender, reply.ToString(), null); } }