Merge branch 'master' into angular_ui
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user