/** * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal */ import * as fs from 'fs'; import * as path from 'path'; import { JobManager, Job } from './jobs'; import { ConsoleLogger } from 'mol-util/console-logger'; import { resolveJob } from './query'; import { StructureCache } from './structure-wrapper'; import { now } from 'mol-util/now'; import { PerformanceMonitor } from 'mol-util/performance-monitor'; import { QueryName } from './api'; export type LocalInput = { input: string, output: string, query: QueryName, modelNums?: number[], params?: any, binary?: boolean }[]; export async function runLocal(input: LocalInput) { if (!input.length) { ConsoleLogger.error('Local', 'No input'); return; } for (const job of input) { const binary = /\.bcif/.test(job.output); JobManager.add({ entryId: job.input, queryName: job.query, queryParams: job.params || { }, options: { modelNums: job.modelNums, outputFilename: job.output, binary } }); } JobManager.sort(); const started = now(); let job: Job | undefined = JobManager.getNext(); let key = job.key; let progress = 0; while (job) { try { const encoder = await resolveJob(job); const writer = wrapFileToWriter(job.outputFilename!); encoder.writeTo(writer); writer.end(); ConsoleLogger.logId(job.id, 'Query', 'Written.'); if (JobManager.hasNext()) { job = JobManager.getNext(); if (key !== job.key) StructureCache.expire(key); key = job.key; } else { break; } } catch (e) { ConsoleLogger.errorId(job.id, e); } ConsoleLogger.log('Progress', `[${++progress}/${input.length}] after ${PerformanceMonitor.format(now() - started)}.`); } ConsoleLogger.log('Progress', `Done in ${PerformanceMonitor.format(now() - started)}.`); StructureCache.expireAll(); } export function wrapFileToWriter(fn: string) { const w = { open(this: any) { if (this.opened) return; makeDir(path.dirname(fn)); this.file = fs.openSync(fn, 'w'); this.opened = true; }, writeBinary(this: any, data: Uint8Array) { this.open(); fs.writeSync(this.file, new Buffer(data.buffer)); return true; }, writeString(this: any, data: string) { this.open(); fs.writeSync(this.file, data); return true; }, end(this: any) { if (!this.opened || this.ended) return; fs.close(this.file, function () { }); this.ended = true; }, file: 0, ended: false, opened: false }; return w; } function makeDir(path: string, root?: string): boolean { let dirs = path.split(/\/|\\/g), dir = dirs.shift(); root = (root || '') + dir + '/'; try { fs.mkdirSync(root); } catch (e) { if (!fs.statSync(root).isDirectory()) throw new Error(e); } return !dirs.length || makeDir(dirs.join('/'), root); }