Beispiel #1
0
            private async Task <LogItem> ProcessItem(EncodeServer server, QueueItem src)
            {
                DateTime now = DateTime.Now;

                if (File.Exists(src.Path) == false)
                {
                    return(FailLogItem(src.Path, "入力ファイルが見つかりません", now, now));
                }

                bool   isMp4    = src.Path.ToLower().EndsWith(".mp4");
                string dstpath  = Path.Combine(encoded, Path.GetFileName(src.Path));
                string srcpath  = src.Path;
                string localsrc = null;
                string localdst = dstpath;

                // ハッシュがある(ネットワーク経由)の場合はローカルにコピー
                if (hashList != null)
                {
                    localsrc = tmpBase + "-in" + Path.GetExtension(srcpath);
                    string name = Path.GetFileName(srcpath);
                    if (hashList.ContainsKey(name) == false)
                    {
                        return(FailLogItem(src.Path, "入力ファイルのハッシュがありません", now, now));
                    }

                    byte[] hash = await HashUtil.CopyWithHash(srcpath, localsrc);

                    var refhash = hashList[name];
                    if (hash.SequenceEqual(refhash) == false)
                    {
                        File.Delete(localsrc);
                        return(FailLogItem(src.Path, "コピーしたファイルのハッシュが一致しません", now, now));
                    }

                    srcpath  = localsrc;
                    localdst = tmpBase + "-out.mp4";
                }

                string json = Path.Combine(
                    Path.GetDirectoryName(localdst),
                    Path.GetFileNameWithoutExtension(localdst)) + "-enc.json";
                string logpath = Path.Combine(
                    Path.GetDirectoryName(dstpath),
                    Path.GetFileNameWithoutExtension(dstpath)) + "-enc.log";
                string args    = server.MakeAmatsukazeArgs(isMp4, srcpath, localdst, json);
                string exename = server.appData.setting.AmatsukazePath;

                Util.AddLog(id, "エンコード開始: " + src.Path);
                Util.AddLog(id, "Args: " + exename + " " + args);

                DateTime start = DateTime.Now;

                var psi = new ProcessStartInfo(exename, args)
                {
                    UseShellExecute        = false,
                    WorkingDirectory       = Directory.GetCurrentDirectory(),
                    RedirectStandardError  = true,
                    RedirectStandardOutput = true,
                    RedirectStandardInput  = false,
                    CreateNoWindow         = true
                };

                IntPtr affinityMask = new IntPtr((long)server.affinityCreator.GetMask(id));

                Util.AddLog(id, "AffinityMask: " + affinityMask.ToInt64());

                int exitCode = -1;

                logText.Clear();

                try
                {
                    using (var p = Process.Start(psi))
                    {
                        // アフィニティを設定
                        p.ProcessorAffinity = affinityMask;
                        p.PriorityClass     = ProcessPriorityClass.BelowNormal;

                        process = p;

                        using (logWriter = File.Create(logpath))
                        {
                            await Task.WhenAll(
                                RedirectOut(server, p.StandardOutput.BaseStream),
                                RedirectOut(server, p.StandardError.BaseStream),
                                Task.Run(() => p.WaitForExit()));
                        }

                        exitCode = p.ExitCode;
                    }
                }
                catch (Win32Exception w32e)
                {
                    Util.AddLog(id, "Amatsukazeプロセス起動に失敗");
                    throw w32e;
                }
                finally
                {
                    logWriter = null;
                    process   = null;
                }

                DateTime finish = DateTime.Now;

                if (hashList != null)
                {
                    File.Delete(localsrc);
                }

                if (exitCode == 0)
                {
                    // 成功ならログを整形したテキストに置き換える
                    using (var fs = new StreamWriter(File.Create(logpath), Encoding.Default))
                    {
                        foreach (var str in logText.TextLines)
                        {
                            fs.WriteLine(str);
                        }
                    }
                }

                // ログファイルを専用フォルダにコピー
                if (File.Exists(logpath))
                {
                    string logbase = server.GetLogFileBase(start);
                    Directory.CreateDirectory(Path.GetDirectoryName(logbase));
                    string dstlog = logbase + ".txt";
                    File.Copy(logpath, dstlog);

                    if (File.Exists(json))
                    {
                        string dstjson = logbase + ".json";
                        File.Move(json, dstjson);
                        json = dstjson;
                    }
                }

                if (exitCode == 0)
                {
                    // 成功
                    var log = LogFromJson(isMp4, json, start, finish);

                    // ハッシュがある(ネットワーク経由)の場合はリモートにコピー
                    if (hashList != null)
                    {
                        log.SrcPath = src.Path;
                        string outbase = Path.GetDirectoryName(dstpath) + "\\" + Path.GetFileNameWithoutExtension(dstpath);
                        for (int i = 0; i < log.OutPath.Count; ++i)
                        {
                            string outext  = Path.GetExtension(log.OutPath[i]);
                            string outpath = outbase + ((i == 0) ? outext : ("-" + i + outext));
                            var    hash    = await HashUtil.CopyWithHash(log.OutPath[i], outpath);

                            string name = Path.GetFileName(outpath);
                            HashUtil.AppendHash(Path.Combine(encoded, "_mp4.hash"), name, hash);
                            File.Delete(log.OutPath[i]);
                            log.OutPath[i] = outpath;
                        }
                    }

                    return(log);
                }
                else
                {
                    // 失敗
                    return(FailLogItem(src.Path,
                                       "Amatsukaze.exeはコード" + exitCode + "で終了しました。", start, finish));
                }
            }
Beispiel #2
0
        // アイテムのProfileNameからプロファイルを決定して、
        // オプションでwaits!=nullのときはクライアントに通知
        // 戻り値: プロファイルが変更された場合(結果、エラーになった場合も含む)
        private bool UpdateProfileItem(QueueItem item, List <Task> waits)
        {
            var getResult = server.GetProfile(item, item.ProfileName);
            var profile   = (getResult != null) ? ServerSupport.DeepCopy(getResult.Profile) : server.PendingProfile;
            var priority  = (getResult != null && getResult.Priority > 0) ? getResult.Priority : item.Priority;

            if (item.Profile == null ||
                item.Profile.Name != profile.Name ||
                item.Profile.LastUpdate != profile.LastUpdate ||
                item.Priority != priority)
            {
                // 変更
                item.Profile  = profile;
                item.Priority = priority;

                // ハッシュリスト取得
                if (profile != server.PendingProfile && // ペンディングの場合は決定したときに実行される
                    item.IsSeparateHashRequired)
                {
                    var hashpath = Path.GetDirectoryName(item.SrcPath) + ".hash";
                    if (hashCache.ContainsKey(hashpath) == false)
                    {
                        if (File.Exists(hashpath) == false)
                        {
                            item.State      = QueueState.LogoPending;
                            item.FailReason = "ハッシュファイルがありません: " + hashpath;
                            return(true);
                        }
                        else
                        {
                            try
                            {
                                hashCache.Add(hashpath, new DirHash()
                                {
                                    DirPath  = hashpath,
                                    HashDict = HashUtil.ReadHashFile(hashpath)
                                });
                            }
                            catch (IOException e)
                            {
                                item.State      = QueueState.LogoPending;
                                item.FailReason = "ハッシュファイルの読み込みに失敗: " + e.Message;
                                return(true);
                            }
                        }
                    }

                    var cacheItem = hashCache[hashpath];
                    var filename  = item.FileName;

                    if (cacheItem.HashDict.ContainsKey(filename) == false)
                    {
                        item.State      = QueueState.LogoPending;
                        item.FailReason = "ハッシュファイルにこのファイルのハッシュがありません";
                        return(true);
                    }

                    item.Hash = cacheItem.HashDict[filename];
                }

                server.ReScheduleQueue();
                UpdateQueueItem(item, waits);

                waits?.Add(ClientQueueUpdate(new QueueUpdate()
                {
                    Type = UpdateType.Add,
                    Item = item
                }));

                return(true);
            }

            return(false);
        }
Beispiel #3
0
        private async Task StartEncode()
        {
            NowEncoding = true;

            // 待たなくてもいいタスクリスト
            var waitList = new List <Task>();

            // 状態を更新
            waitList.Add(RequestState());

            try
            {
                while (queue.Count > 0)
                {
                    // 不正な設定は強制的に直しちゃう
                    if (appData.setting.NumParallel <= 0 ||
                        appData.setting.NumParallel > 64)
                    {
                        appData.setting.NumParallel = 1;
                    }

                    int numParallel = appData.setting.NumParallel;

                    // 足りない場合は追加
                    while (taskList.Count < numParallel)
                    {
                        taskList.Add(new EncodeTask()
                        {
                            id          = taskList.Count,
                            consoleText = new ConsoleText(500),
                            logText     = new ConsoleText(1 * 1024 * 1024)
                        });
                    }
                    // 多すぎる場合は削除
                    while (taskList.Count > numParallel)
                    {
                        taskList.RemoveAt(taskList.Count - 1);
                    }

                    affinityCreator.NumProcess = numParallel;

                    var dir = queue[0];

                    Dictionary <string, byte[]> hashList = null;
                    if (dir.Path.StartsWith("\\\\"))
                    {
                        var hashpath = dir.Path + ".hash";
                        if (File.Exists(hashpath) == false)
                        {
                            throw new IOException("ハッシュファイルがありません: " + hashpath + "\r\n" +
                                                  "ネットワーク経由の場合はBatchHashCheckerによるハッシュファイル生成が必須です。");
                        }
                        hashList = HashUtil.ReadHashFile(hashpath);
                    }

                    Task[] tasks = new Task[numParallel];
                    for (int i = 0; i < numParallel; ++i)
                    {
                        taskList[i].hashList = hashList;
                        taskList[i].tmpBase  = Util.CreateTmpFile(appData.setting.WorkPath);
                        tasks[i]             = taskList[i].ProcessDiretoryItem(this, dir);
                    }

                    await Task.WhenAll(tasks);

                    for (int i = 0; i < numParallel; ++i)
                    {
                        File.Delete(taskList[i].tmpBase);
                    }

                    if (encodePaused)
                    {
                        break;
                    }
                    queue.Remove(dir);
                    waitList.Add(client.OnQueueUpdate(new QueueUpdate()
                    {
                        Type    = UpdateType.Remove,
                        DirPath = dir.Path,
                    }));
                }
            }
            catch (Exception e)
            {
                waitList.Add(AddEncodeLog(
                                 "エラーでエンコードが停止しました: " + e.Message));
            }

            NowEncoding = false;

            // 状態を更新
            waitList.Add(RequestState());

            await Task.WhenAll(waitList.ToArray());
        }