Merge branch 'master' into angular_ui

This commit is contained in:
Kenneth Skovhede
2015-10-04 17:15:02 +02:00
5 changed files with 119 additions and 4 deletions
+32
View File
@@ -57,6 +57,16 @@ namespace Duplicati.Server
/// </summary>
public static Duplicati.Library.Utility.WorkerThread<Runner.IRunnerData> WorkThread;
/// <summary>
/// List of completed task results
/// </summary>
public static List<KeyValuePair<long, Exception>> TaskResultCache = new List<KeyValuePair<long, Exception>>();
/// <summary>
/// The maximum number of completed task results to keep in memory
/// </summary>
private static int MAX_TASK_RESULT_CACHE_SIZE = 100;
/// <summary>
/// The thread running the ping-pong handler
/// </summary>
@@ -445,6 +455,28 @@ namespace Duplicati.Server
Program.Scheduler.NewSchedule += new EventHandler(SignalNewEvent);
Program.WorkThread.OnError += (worker, task, exception) => { Program.DataConnection.LogError(task == null ? null : task.BackupID, "Error in worker", exception); };
Action<long, Exception> registerTaskResult = (id, ex) => {
lock(Program.MainLock) {
// If the new results says it crashed, we store that instead of success
if (Program.TaskResultCache.Count > 0 && Program.TaskResultCache.Last().Key == id)
{
if (ex != null && Program.TaskResultCache.Last().Value == null)
Program.TaskResultCache.RemoveAt(Program.TaskResultCache.Count - 1);
else
return;
}
Program.TaskResultCache.Add(new KeyValuePair<long, Exception>(id, ex));
while(Program.TaskResultCache.Count > MAX_TASK_RESULT_CACHE_SIZE)
Program.TaskResultCache.RemoveAt(0);
}
};
Program.WorkThread.CompletedWork += (worker, task) => { registerTaskResult(task.TaskID, null); };
Program.WorkThread.OnError += (worker, task, exception) => { registerTaskResult(task.TaskID, exception); };
Program.WebServer = new WebServer.Server(commandlineOptions);
if (Program.WebServer.Port != DataConnection.ApplicationSettings.LastWebserverPort)
+1 -1
View File
@@ -172,7 +172,7 @@ namespace Duplicati.Server.WebServer
module = module.Trim('/');
var key = string.Join("/", request.Uri.Segments.Skip(API_URI_SEGMENTS + 1)).Trim('/');
var key = string.Join("", request.Uri.Segments.Skip(API_URI_SEGMENTS + 1)).Trim('/');
var method = request.Method;
if (!string.IsNullOrWhiteSpace(request.Headers["X-HTTP-Method-Override"]))
@@ -297,7 +297,7 @@ namespace Duplicati.Server.WebServer.RESTMethods
switch (operation)
{
case "files":
SearchFiles(bk, parts.Last().Split(new char[] { '/' }, 2).LastOrDefault(), info);
SearchFiles(bk, parts.Last().Split(new char[] { '/' }, 2).Skip(1).FirstOrDefault(), info);
return;
case "log":
FetchLogData(bk, info);
@@ -156,6 +156,9 @@ namespace Duplicati.Server.WebServer.RESTMethods
using(var tf = new Duplicati.Library.Utility.TempFile())
data.Backup.DBPath = tf;
data.Backup.Filters = data.Backup.Filters ?? new Duplicati.Server.Serialization.Interface.IFilter[0];
data.Backup.Settings = data.Backup.Settings ?? new Duplicati.Server.Serialization.Interface.ISetting[0];
Program.DataConnection.RegisterTemporaryBackup(data.Backup);
info.OutputOK(new { status = "OK", ID = data.Backup.ID });
+82 -2
View File
@@ -14,11 +14,91 @@
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System;
using System.Linq;
using System.Collections.Generic;
namespace Duplicati.Server.WebServer.RESTMethods
{
{
public class Task : IRESTMethodGET, IRESTMethodPOST
{
public void GET(string key, RequestInfo info)
{
var parts = (key ?? "").Split(new char[] { '/' }, 2);
long taskid;
if (parts.Length == 2 && long.TryParse(parts.First(), out taskid))
{
var task = Program.WorkThread.CurrentTask;
var tasks = Program.WorkThread.CurrentTasks;
if (task != null && task.TaskID == taskid)
{
info.OutputOK(new { Status = "Running" });
return;
}
task = tasks.Where(x => x.TaskID == taskid).FirstOrDefault();
if (tasks.Where(x => x.TaskID == taskid).FirstOrDefault() == null)
{
KeyValuePair<long, Exception>[] matches;
lock(Program.MainLock)
matches = Program.TaskResultCache.Where(x => x.Key == taskid).ToArray();
if (matches.Length == 0)
info.ReportClientError("No such task found", System.Net.HttpStatusCode.NotFound);
else
info.OutputOK(new {
Status = matches[0].Value == null ? "Completed" : "Failed",
ErrorMessage = matches[0].Value == null ? null : matches[0].Value.Message,
Exception = matches[0].Value == null ? null : matches[0].Value.ToString()
});
}
else
{
info.OutputOK(new { Status = "Waiting" });
}
}
else
{
info.ReportClientError("Invalid request");
}
}
public void POST(string key, RequestInfo info)
{
var parts = (key ?? "").Split(new char[] { '/' }, 2);
long taskid;
if (parts.Length == 2 && long.TryParse(parts.First(), out taskid))
{
var task = Program.WorkThread.CurrentTask;
var tasks = Program.WorkThread.CurrentTasks;
if (task != null)
tasks.Insert(0, task);
task = tasks.Where(x => x.TaskID == taskid).FirstOrDefault();
if (task == null)
{
info.ReportClientError("No such task", System.Net.HttpStatusCode.NotFound);
return;
}
switch (parts.Last().ToLowerInvariant())
{
case "abort":
task.Abort();
info.OutputOK();
return;
case "stop":
task.Stop();
info.OutputOK();
return;
}
}
info.ReportClientError("Invalid or missing task id");
}
}
}