/// <summary> /// Processes the result of fetching an individual file. /// </summary> /// <param name="state">Indicates the state of the ongoing fetch operation (as set up in FetchObj).</param> /// <param name="index">If ROOT_FILE_INDEX, then this is a result for the main file; else this is a result for /// the resource file with that index.</param> /// <param name="status">The status indicating if the download succeed</param> /// <param name="data">The data that was downloaded.</param> private void ProcessFileFetchResult(FetchOperationState state, int index, PolyStatus status, byte[] data) { if (state.pendingFiles == 0) { // Another request for this format failed, so we ignore any further responses. return; } if (!status.ok) { // This request failed, so we set pendingFiles to 0 so we ignore any further responses, and callback with // an error message. state.pendingFiles = 0; state.completionCallback(state.asset, PolyStatus.Error(status, "Failed to fetch file #{0}", index)); return; } PolyFormat package = state.packageBeingFetched; PolyFile file = index == ROOT_FILE_INDEX ? package.root : package.resources[index]; file.contents = data; --state.pendingFiles; if (state.progressCallback != null) { state.progressCallback(state.asset, 1.0f - ((float)state.pendingFiles / state.totalFiles)); } if (state.pendingFiles <= 0) { // All files done, call callback indicating success. state.completionCallback(state.asset, PolyStatus.Success()); } }
public void FetchFormatFiles(PolyAsset asset, PolyFormatType formatType, PolyApi.FetchFormatFilesCallback completionCallback, FetchProgressCallback progressCallback = null) { PolyUtils.AssertNotNull(asset, "Asset can't be null."); PolyUtils.AssertNotNull(formatType, "formatType can't be null."); PolyFormat packageToFetch = asset.GetFormatIfExists(formatType); if (packageToFetch == null) { if (completionCallback != null) { completionCallback(asset, PolyStatus.Error("Format type not present in asset")); } return; } PolyUtils.AssertNotNull(packageToFetch.root, "packageToFetch.root can't be null."); PolyUtils.AssertNotNull(packageToFetch.root.url, "packageToFetch.root.url can't be null."); PolyUtils.AssertNotNull(packageToFetch.resources, "packageToFetch.resources can't be null."); string accessToken = GetAccessToken(); FetchOperationState state = new FetchOperationState(); state.asset = asset; state.completionCallback = completionCallback; state.progressCallback = progressCallback; state.packageBeingFetched = packageToFetch; // Indicates how many files are pending download (1 for main file + 1 for each resource). state.totalFiles = state.pendingFiles = 1 + packageToFetch.resources.Count; // Note that the callbacks are asynchronous so they may complete in any order. What we do know is that they // will all be called on the main thread, so they won't be called concurrently. long maxCacheAge = asset.IsMutable ? MUTABLE_ASSET_MAX_CACHE_AGE : IMMUTABLE_ASSET_MAX_CACHE_AGE; PolyClientUtils.GetRawFileBytes(packageToFetch.root.url, accessToken, maxCacheAge, (PolyStatus status, byte[] data) => { ProcessFileFetchResult(state, ROOT_FILE_INDEX, status, data); }); for (int i = 0; i < packageToFetch.resources.Count; i++) { int thisIndex = i; // copy of variable, for closure below. PolyClientUtils.GetRawFileBytes(packageToFetch.resources[i].url, accessToken, maxCacheAge, (status, data) => { ProcessFileFetchResult(state, thisIndex, status, data); }); } }
public DataTable ExCommandToDatatableNew(DbCommand cmdX, string Name, string Namespace, int timeout_seconds) { Tracing.VerboseDAL(cmdX.CommandText); /* [dlatikay 20160801] I-1606-2237 site of ultimate improvement of (not done yet, considered MemoryFailPoint) * [dlatikay 20160909] I-1609-1674, MEA-2016-00401: this primordial version proved to be the fastest */ if (timeout_seconds > 0) { /* we need to roll our own timeout, * would be must easier with 4.5, but as we're still stuck with 4.0 (also for MONO compatibility reasons), we're inspired by: * http://stackoverflow.com/questions/18760252/timeout-an-async-method-implemented-with-taskcompletionsource/18760624#18760624 */ var parms = new FetchOperationState() { cmdX = cmdX, Name = Name, Namespace = Namespace, timeout_seconds = timeout_seconds }; try { /* we give the envelope one second more time, * so the underlying RDBMS client code has the chance to not fail to recognize its own timeout, as it should (but does not, * at least not Managed Oracle, as we painfully found out) */ FetchOperationAsync(parms, CancellationToken.None, timeout_seconds + 1).Wait(); } catch (Exception tox) { #if DEBUG Tracing.WarningDAL("{0}", tox.ToString()); #endif while (tox is AggregateException) { tox = tox.InnerException; } if (tox is TaskCanceledException) { throw new TimeoutException(String.Format("DAL DB Timeout expired ({0}sec)", timeout_seconds), tox); } } return(parms.dt); } else { /* simple synchronous variant */ using (DbDataAdapter ad = db.NewDataAdapter()) { ad.SelectCommand = cmdX; var dt = new DataTable(Name, Namespace); ad.Fill(dt); return(dt); } } /* unfortunately, this by far cuter variant is considerable slower (>30%)! */ //if (timeout_seconds > 0) cmdX.CommandTimeout = timeout_seconds; //using (var dr = cmdX.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SingleResult)) //{ // var dt = new DataTable(Name, Namespace); // dt.Load(dr, LoadOption.OverwriteChanges, (s, e) => // { // if (e.Errors != null) Tracing.VerboseDAL("dt.load.error {0}", e.Errors.ToString()); // }); // foreach (DataColumn col in dt.Columns) // { // col.ReadOnly = false; /* http://stackoverflow.com/questions/5434833/readonlyexception-datatable-datarow-column-x-is-read-only */ // if (col.MaxLength > 0) col.MaxLength = -1; /* https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Data.DataColumn.MaxLength);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.0);k(DevLang-csharp)&rd=true */ // } // return dt; //} }