using Newtonsoft.Json; using SteamWare; using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; namespace WebLCP.WUC { public partial class mod_startJob : BaseUserControl { public Dictionary errorList { get { Dictionary answ = new Dictionary(); string rawData = memLayer.ML.StringSessionObj("errorList"); if (!string.IsNullOrEmpty(rawData)) { answ = JsonConvert.DeserializeObject>(rawData); } return answ; } set { string jsonData = JsonConvert.SerializeObject(value); memLayer.ML.setSessionVal("errorList", jsonData); } } public Dictionary successList { get { Dictionary answ = new Dictionary(); string rawData = memLayer.ML.StringSessionObj("successList"); if (!string.IsNullOrEmpty(rawData)) { answ = JsonConvert.DeserializeObject>(rawData); } return answ; } set { string jsonData = JsonConvert.SerializeObject(value); memLayer.ML.setSessionVal("successList", jsonData); } } protected void Page_Load(object sender, EventArgs e) { if (devicesAuthProxy.stObj.utente == "") { Response.Redirect("Default"); } dataLayer.man.cleanupTempDir(); dataLayer.man.checkJobs(); if (!Page.IsPostBack) { dataLayer.man.cleanupJobsDir(); } } protected void lbtUpload_Click(object sender, EventArgs e) { if (devicesAuthProxy.stObj.utente != "") { checkAndUploadFile(); // ricarico x evitare problemi di file già "in pancia" //FUplCsv.PostedFile.InputStream.Dispose(); FUplCsv.Dispose(); } else { Response.Redirect("Default"); } } /// /// Restituisce il nome del JOB caricato come descrizione digitata + nome file uploaded /// protected string jobDescription { get { string answ = $"{txtJobDescr.Text.Trim()} | {FUplCsv.FileName}"; return answ; } } private void checkAndUploadFile() { // init dei dizionari errori/successi Dictionary newErrorList = new Dictionary(); Dictionary newSuccessList = new Dictionary(); string jobName = ""; string sourceDir = ""; // STEP1: inizio controlli su nomi... if (FUplCsv.FileName != "" && (FUplCsv.FileName.EndsWith(".txt") || FUplCsv.FileName.EndsWith(".csv"))) { newSuccessList.Add("FILE INPUT", "OK Filename format"); } else { newErrorList.Add("FILE INPUT", "WRONG Filename format (only *.csv and *.txt)"); } // STEP 2: se NON HO errori faccio controllo files if (newErrorList.Count == 0) { jobName = $"TMP{DateTime.Now.ToString("yyyyMMdd_HHmmss_fff")}"; // carico localmente files sourceDir = uploadLocally(jobName); // controllo i files... checkFilesUploaded(sourceDir, ref newErrorList); // elimino file locali... fileMover.obj.setDirectory(sourceDir); fileMover.obj.eliminaDir(); } //step 3: se tutto ok procedo con upload... if (newErrorList.Count == 0) { // creo record DS_App.JobsListDataTable tabJobs = dataLayer.man.taJL.insertNew(jobDescription, devicesAuthProxy.stObj.utente); if (tabJobs.Count == 1) { /************************************************* * CON il nome JOB (ID) creato... * - devo creare una folder x il job * - nella folder devo salvare i 2 files * - sposto folder in area IN * - devo creare un file *.req (anche vuoto) della richiesta di calcolo (in area IN) *************************************************/ // recupero riga... DS_App.JobsListRow currJob = tabJobs[0]; // uso il nome job creato x le path temporanee con 16 char... jobName = "J" + currJob.JobId.ToString("D9"); // carico localmente files sourceDir = uploadLocally(jobName); // sposto su cluster string destDir = moveToCluster(jobName, sourceDir); // aggiorno su DB updateDbRecord(currJob, destDir); } else { newErrorList.Add("DB_JOB", "Error creating record on DB"); } } // se ho errori mostro...... if (newErrorList.Count + newSuccessList.Count > 0) { errorList = newErrorList; successList = newSuccessList; raiseEvent(ucEvType.ReqUpdateParent); } } /// /// Controllo dei fiels caricati localmente /// /// private void checkFilesUploaded(string sourceDir, ref Dictionary newErrorList) { string[] linesDbIn; string regExpHead = @"^\w*;\w*;\w*;\w*$"; ; string regExpBodyA = memLayer.ML.CRS("regExpBodyA");// @"^\d+;(0|1);(pos|neg);\-?\d+(\,\d*)*$"; // controllo DB_IN linesDbIn = File.ReadAllLines($"{sourceDir}DB_INPUT.csv"); checkFile(linesDbIn, regExpHead, regExpBodyA, "DB_INPUT.csv", ref newErrorList); } /// /// controllo il file... /// /// /// /// private void checkFile(string[] linesDbIn, string regExpHead, string regExpBody, string fileName, ref Dictionary newErrorList) { // controllo abbia ALMENO 2 linee (testata + valore) if (linesDbIn.Length > 1) { Regex rgxHead = new Regex(regExpHead); Regex rgxBody = new Regex(regExpBody); // controllo linea intestazione if (!rgxHead.IsMatch(linesDbIn[0])) { newErrorList.Add($"{fileName}-Header", $"HEADER ERROR (mismatch): found --> {linesDbIn[0]}"); } // controllo linee successive, SE supero i 10 errori ESCO comunque... int maxErrors = memLayer.ML.CRI("maxErrors"); for (int i = 1; i < linesDbIn.Length; i++) { if (!rgxBody.IsMatch(linesDbIn[i])) { newErrorList.Add($"{fileName}-Line[{i}]", $"DATA ERROR (mismatch): --> {linesDbIn[i]}"); maxErrors--; } if (maxErrors <= 0) { break; } } } else { newErrorList.Add($"{fileName}-LineCount", "Expected almost 2 lines (header + data)"); } } /// /// aggiornamento record su DB post upload /// /// /// private void updateDbRecord(DS_App.JobsListRow currJob, string destDir) { // registro trasferimento effettuato... int sizeKb = (FUplCsv.PostedFile.ContentLength) / 1024; // update record! dataLayer.man.taJL.updateUpload(currJob.JobId, DateTime.Now, sizeKb, destDir); } /// /// Sposta i dati da directory locale a cluster /// /// /// /// private static string moveToCluster(string jobName, string sourceDir) { // creo cartella in server target string destDir = $"{memLayer.ML.CRS("clusterBaseDir")}\\IN\\"; // @"L:\IN\"; try { logger.lg.scriviLog($"Richiesta copia directory:{sourceDir} --> {destDir}\\{jobName}", tipoLog.INFO); // sposto folder in dir target.. fileMover.DirectoryCopy(sourceDir, destDir + $"{jobName}\\", true); } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in copia directory:{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } try { if (memLayer.ML.CRB("reqWriteLocal")) { string srcDirOnly = sourceDir.Replace($"{jobName}\\", ""); logger.lg.scriviLog($"Richiesta scrittura file IN LOCALE: {srcDirOnly}\\{jobName}.req", tipoLog.INFO); // aggiungo file di request locale... File.WriteAllText($"{srcDirOnly}\\{jobName}.req", ""); // lo sposto! fileMover.obj.copiaFile(srcDirOnly, destDir, $"{jobName}.req"); } else { logger.lg.scriviLog($"Richiesta scrittura file IN remoto :{destDir}\\{jobName}.req", tipoLog.INFO); // aggiungo file di request... File.WriteAllText($"{destDir}\\{jobName}.req", ""); } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in creazione file req:{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } return destDir; } /// /// Carica localmente (sul server) i dati e restituisce path locale (compreso di jobName nella path) /// /// /// private string uploadLocally(string jobName) { // creo upload dir... string sourceDir = Server.MapPath($"{memLayer.ML.CRS("tempUploadDir")}\\{jobName}\\"); fileMover.obj.setDirectory(sourceDir); fileMover.obj.checkDir(); // proseguo con upload files... FUplCsv.SaveAs($"{sourceDir}DB_INPUT.csv"); return sourceDir; } } }