synchronize write and scp

This commit is contained in:
Snarling 2022-08-17 17:11:59 -04:00
parent ba5b0be7f4
commit 95a1c18139
3 changed files with 38 additions and 78 deletions

@ -829,11 +829,7 @@ const base: InternalAPI<NS> = {
}, },
scp: scp:
(ctx: NetscriptContext) => (ctx: NetscriptContext) =>
async ( (_scriptname: unknown, _destination: unknown, _source: unknown = ctx.workerScript.hostname): boolean => {
_scriptname: unknown,
_destination: unknown,
_source: unknown = ctx.workerScript.hostname,
): Promise<boolean> => {
const destination = helpers.string(ctx, "destination", _destination); const destination = helpers.string(ctx, "destination", _destination);
const source = helpers.string(ctx, "source", _source); const source = helpers.string(ctx, "source", _source);
if (Array.isArray(_scriptname)) { if (Array.isArray(_scriptname)) {
@ -843,14 +839,12 @@ const base: InternalAPI<NS> = {
throw helpers.makeRuntimeErrorMsg(ctx, "No scripts to copy"); throw helpers.makeRuntimeErrorMsg(ctx, "No scripts to copy");
} }
let res = true; let res = true;
await Promise.all( scripts.map(function (script) {
scripts.map(async function (script) { if (!NetscriptFunctions(ctx.workerScript).scp(script, destination, source)) {
if (!(await NetscriptFunctions(ctx.workerScript).scp(script, destination, source))) { res = false;
res = false; }
} });
}), return res;
);
return Promise.resolve(res);
} }
const scriptName = helpers.string(ctx, "scriptName", _scriptname); const scriptName = helpers.string(ctx, "scriptName", _scriptname);
@ -880,18 +874,18 @@ const base: InternalAPI<NS> = {
if (!found) { if (!found) {
helpers.log(ctx, () => `File '${scriptName}' does not exist.`); helpers.log(ctx, () => `File '${scriptName}' does not exist.`);
return Promise.resolve(false); return false;
} }
for (let i = 0; i < destServer.messages.length; ++i) { for (let i = 0; i < destServer.messages.length; ++i) {
if (destServer.messages[i] === scriptName) { if (destServer.messages[i] === scriptName) {
helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`); helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`);
return Promise.resolve(true); // Already exists return true; // Already exists
} }
} }
destServer.messages.push(scriptName); destServer.messages.push(scriptName);
helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`); helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`);
return Promise.resolve(true); return true;
} }
// Scp for text files // Scp for text files
@ -905,7 +899,7 @@ const base: InternalAPI<NS> = {
} }
if (txtFile === undefined) { if (txtFile === undefined) {
helpers.log(ctx, () => `File '${scriptName}' does not exist.`); helpers.log(ctx, () => `File '${scriptName}' does not exist.`);
return Promise.resolve(false); return false;
} }
for (let i = 0; i < destServer.textFiles.length; ++i) { for (let i = 0; i < destServer.textFiles.length; ++i) {
@ -913,13 +907,13 @@ const base: InternalAPI<NS> = {
// Overwrite // Overwrite
destServer.textFiles[i].text = txtFile.text; destServer.textFiles[i].text = txtFile.text;
helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`); helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`);
return Promise.resolve(true); return true;
} }
} }
const newFile = new TextFile(txtFile.fn, txtFile.text); const newFile = new TextFile(txtFile.fn, txtFile.text);
destServer.textFiles.push(newFile); destServer.textFiles.push(newFile);
helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`); helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`);
return Promise.resolve(true); return true;
} }
// Scp for script files // Scp for script files
@ -932,7 +926,7 @@ const base: InternalAPI<NS> = {
} }
if (sourceScript == null) { if (sourceScript == null) {
helpers.log(ctx, () => `File '${scriptName}' does not exist.`); helpers.log(ctx, () => `File '${scriptName}' does not exist.`);
return Promise.resolve(false); return false;
} }
// Overwrite script if it already exists // Overwrite script if it already exists
@ -943,11 +937,11 @@ const base: InternalAPI<NS> = {
// If it's the exact same file don't actually perform the // If it's the exact same file don't actually perform the
// copy to avoid recompiling uselessly. Players tend to scp // copy to avoid recompiling uselessly. Players tend to scp
// liberally. // liberally.
if (oldScript.code === sourceScript.code) return Promise.resolve(true); if (oldScript.code === sourceScript.code) return true;
oldScript.code = sourceScript.code; oldScript.code = sourceScript.code;
oldScript.ramUsage = sourceScript.ramUsage; oldScript.ramUsage = sourceScript.ramUsage;
oldScript.markUpdated(); oldScript.markUpdated();
return Promise.resolve(true); return true;
} }
} }
@ -958,13 +952,8 @@ const base: InternalAPI<NS> = {
newScript.server = destServer.hostname; newScript.server = destServer.hostname;
destServer.scripts.push(newScript); destServer.scripts.push(newScript);
helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`); helpers.log(ctx, () => `File '${scriptName}' copied over to '${destServer?.hostname}'.`);
return new Promise((resolve) => { newScript.updateRamUsage(Player, destServer.scripts);
if (destServer === null) { return true;
resolve(false);
return;
}
newScript.updateRamUsage(Player, destServer.scripts).then(() => resolve(true));
});
}, },
ls: ls:
(ctx: NetscriptContext) => (ctx: NetscriptContext) =>
@ -1501,7 +1490,7 @@ const base: InternalAPI<NS> = {
}, },
write: write:
(ctx: NetscriptContext) => (ctx: NetscriptContext) =>
(_port: unknown, data: unknown = "", _mode: unknown = "a"): Promise<void> => { (_port: unknown, data: unknown = "", _mode: unknown = "a"): void => {
const port = helpers.string(ctx, "port", _port); const port = helpers.string(ctx, "port", _port);
const mode = helpers.string(ctx, "mode", _mode); const mode = helpers.string(ctx, "mode", _mode);
if (isString(port)) { if (isString(port)) {
@ -1545,7 +1534,7 @@ const base: InternalAPI<NS> = {
const txtFile = getTextFile(fn, server); const txtFile = getTextFile(fn, server);
if (txtFile == null) { if (txtFile == null) {
createTextFile(fn, String(data), server); createTextFile(fn, String(data), server);
return Promise.resolve(); return;
} }
if (mode === "w") { if (mode === "w") {
txtFile.write(String(data)); txtFile.write(String(data));
@ -1553,7 +1542,7 @@ const base: InternalAPI<NS> = {
txtFile.append(String(data)); txtFile.append(String(data));
} }
} }
return Promise.resolve(); return;
} else { } else {
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${port}`); throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${port}`);
} }

@ -44,7 +44,7 @@ const memCheckGlobalKey = ".__GLOBAL__";
* @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to * @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to
* keep track of what functions have/havent been accounted for * keep track of what functions have/havent been accounted for
*/ */
async function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: string): Promise<RamCalculation> { function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: string): RamCalculation {
try { try {
/** /**
* Maps dependent identifiers to their dependencies. * Maps dependent identifiers to their dependencies.
@ -88,47 +88,22 @@ async function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], co
while (parseQueue.length > 0) { while (parseQueue.length > 0) {
const nextModule = parseQueue.shift(); const nextModule = parseQueue.shift();
if (nextModule === undefined) throw new Error("nextModule should not be undefined"); if (nextModule === undefined) throw new Error("nextModule should not be undefined");
if (nextModule.startsWith("https://") || nextModule.startsWith("http://")) continue;
// Additional modules can either be imported from the web (in which case we use let script = null;
// a dynamic import), or from other in-game scripts const fn = nextModule.startsWith("./") ? nextModule.slice(2) : nextModule;
let code; for (const s of otherScripts) {
if (nextModule.startsWith("https://") || nextModule.startsWith("http://")) { if (areImportsEquals(s.filename, fn)) {
try { script = s;
// eslint-disable-next-line no-await-in-loop break;
const module = await eval("import(nextModule)");
code = "";
for (const prop in module) {
if (typeof module[prop] === "function") {
code += module[prop].toString() + ";\n";
}
}
} catch (e) {
console.error(`Error dynamically importing module from ${nextModule} for RAM calculations: ${e}`);
return { cost: RamCalculationErrorCode.URLImportError };
} }
} else {
if (!Array.isArray(otherScripts)) {
console.warn(`parseOnlyRamCalculate() not called with array of scripts`);
return { cost: RamCalculationErrorCode.ImportError };
}
let script = null;
const fn = nextModule.startsWith("./") ? nextModule.slice(2) : nextModule;
for (const s of otherScripts) {
if (areImportsEquals(s.filename, fn)) {
script = s;
break;
}
}
if (script == null) {
return { cost: RamCalculationErrorCode.ImportError }; // No such script on the server
}
code = script.code;
} }
parseCode(code, nextModule); if (script == null) {
return { cost: RamCalculationErrorCode.ImportError }; // No such script on the server
}
parseCode(script.code, nextModule);
} }
// Finally, walk the reference map and generate a ram cost. The initial set of keys to scan // Finally, walk the reference map and generate a ram cost. The initial set of keys to scan
@ -406,13 +381,9 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR
* @param {Script[]} otherScripts - All other scripts on the server. * @param {Script[]} otherScripts - All other scripts on the server.
* Used to account for imported scripts * Used to account for imported scripts
*/ */
export async function calculateRamUsage( export function calculateRamUsage(player: IPlayer, codeCopy: string, otherScripts: Script[]): RamCalculation {
player: IPlayer,
codeCopy: string,
otherScripts: Script[],
): Promise<RamCalculation> {
try { try {
return await parseOnlyRamCalculate(player, otherScripts, codeCopy); return parseOnlyRamCalculate(player, otherScripts, codeCopy);
} catch (e) { } catch (e) {
console.error(`Failed to parse script for RAM calculations:`); console.error(`Failed to parse script for RAM calculations:`);
console.error(e); console.error(e);

@ -113,8 +113,8 @@ export class Script {
* Calculates and updates the script's RAM usage based on its code * Calculates and updates the script's RAM usage based on its code
* @param {Script[]} otherScripts - Other scripts on the server. Used to process imports * @param {Script[]} otherScripts - Other scripts on the server. Used to process imports
*/ */
async updateRamUsage(player: IPlayer, otherScripts: Script[]): Promise<void> { updateRamUsage(player: IPlayer, otherScripts: Script[]): void {
const res = await calculateRamUsage(player, this.code, otherScripts); const res = calculateRamUsage(player, this.code, otherScripts);
if (res.cost > 0) { if (res.cost > 0) {
this.ramUsage = roundToTwo(res.cost); this.ramUsage = roundToTwo(res.cost);
this.ramUsageEntries = res.entries; this.ramUsageEntries = res.entries;