@openmixer/plugin-qualify 0.18.5 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -730
- package/bin/plugin-qualify-sync.mjs +1 -1
- package/bin/plugin-qualify.mjs +9 -1
- package/dist/clap-qualify.d.ts +1 -1
- package/dist/compare.d.ts +311 -0
- package/dist/compare.js +502 -0
- package/dist/compare.js.map +1 -0
- package/dist/distributed-records.d.ts +0 -2
- package/dist/distributed-records.js +0 -2
- package/dist/distributed-records.js.map +1 -1
- package/dist/host-admission.d.ts +2 -2
- package/dist/host-admission.js +7 -0
- package/dist/host-admission.js.map +1 -1
- package/dist/hosting-codes.generated.d.ts +1 -0
- package/dist/hosting-codes.generated.js +1 -0
- package/dist/hosting-codes.generated.js.map +1 -1
- package/dist/hosting-suitability.d.ts +3 -1
- package/dist/hosting-suitability.js +9 -0
- package/dist/hosting-suitability.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lv2-loader.js +6 -5
- package/dist/lv2-loader.js.map +1 -1
- package/dist/measurement/format.d.ts +15 -0
- package/dist/measurement/format.js +19 -0
- package/dist/measurement/format.js.map +1 -1
- package/dist/measurement/sweep-jsonl.js +5 -1
- package/dist/measurement/sweep-jsonl.js.map +1 -1
- package/dist/measurement-grid.js +1 -1
- package/dist/pins-file.d.ts +22 -2
- package/dist/pins-file.js +118 -17
- package/dist/pins-file.js.map +1 -1
- package/dist/probe-merge.js +6 -0
- package/dist/probe-merge.js.map +1 -1
- package/dist/probe-runner.d.ts +4 -0
- package/dist/probe-runner.js +12 -3
- package/dist/probe-runner.js.map +1 -1
- package/dist/qualification-record.d.ts +33 -1
- package/dist/qualification-record.js +36 -3
- package/dist/qualification-record.js.map +1 -1
- package/dist/qualify-declarations.d.ts +6 -0
- package/dist/qualify-declarations.js +8 -0
- package/dist/qualify-declarations.js.map +1 -1
- package/dist/qualify-isolated.d.ts +16 -3
- package/dist/qualify-isolated.js +31 -3
- package/dist/qualify-isolated.js.map +1 -1
- package/dist/qualify-pool.d.ts +129 -0
- package/dist/qualify-pool.js +290 -0
- package/dist/qualify-pool.js.map +1 -0
- package/dist/qualify-rejudge.js +7 -0
- package/dist/qualify-rejudge.js.map +1 -1
- package/dist/qualify-sync.d.ts +37 -2
- package/dist/qualify-sync.js +148 -24
- package/dist/qualify-sync.js.map +1 -1
- package/dist/records-package.d.ts +5 -0
- package/dist/records-package.js +25 -8
- package/dist/records-package.js.map +1 -1
- package/fixtures/clap-scan/fake.json +8 -2
- package/fixtures/probe-output/success-msi.json +2 -2
- package/package.json +3 -3
- package/src/clap-qualify.ts +1 -1
- package/src/compare.ts +699 -0
- package/src/distributed-records.ts +0 -3
- package/src/host-admission.ts +9 -2
- package/src/hosting-codes.generated.ts +1 -0
- package/src/hosting-suitability.ts +14 -0
- package/src/index.ts +1 -0
- package/src/lv2-loader.ts +5 -4
- package/src/measurement/format.ts +32 -0
- package/src/measurement/sweep-jsonl.ts +5 -1
- package/src/measurement-grid.ts +1 -1
- package/src/pins-file.ts +109 -16
- package/src/probe-merge.ts +4 -0
- package/src/probe-runner.ts +16 -6
- package/src/qualification-record.ts +59 -4
- package/src/qualify-declarations.ts +8 -0
- package/src/qualify-isolated.ts +31 -5
- package/src/qualify-pool.ts +318 -0
- package/src/qualify-rejudge.ts +8 -0
- package/src/qualify-sync.ts +145 -24
- package/src/records-package.ts +25 -8
- package/tools/benchmark.py +9 -3
- package/tools/compare-host.mjs +432 -0
- package/tools/compare-run.mjs +355 -0
- package/tools/descriptors.py +27 -0
- package/tools/isolated-step.mjs +3 -1
- package/tools/lilv_load.py +25 -0
- package/tools/lv2_resolve.py +3 -1
- package/tools/pool-step.mjs +186 -0
- package/tools/scan.py +16 -20
- package/tools/audit-overlap.sh +0 -250
- package/tools/commit-message-check.sh +0 -128
- package/tools/commit-message-patterns.json +0 -41
- package/tools/private-refs-check.sh +0 -90
package/src/qualify-sync.ts
CHANGED
|
@@ -24,21 +24,22 @@ import { homedir, tmpdir } from "node:os";
|
|
|
24
24
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
25
25
|
|
|
26
26
|
import { clapQualifyTools } from "./clap-qualify.js";
|
|
27
|
-
import { DISTRIBUTED_DIR_SYSTEM, EMPTY_LAYER, applyDistributed, distributedUri, hostClassOfBoard, matchDistributed, readBoardModel, readDistributedLayer, type DistributedLayer } from "./distributed-records.js";
|
|
27
|
+
import { DISTRIBUTED_DIR_SYSTEM, EMPTY_LAYER, applyDistributed, distributedUri, hostClassOfBoard, outcomeOfVerdict, matchDistributed, readBoardModel, readDistributedLayer, type DistributedLayer } from "./distributed-records.js";
|
|
28
28
|
import { clapSearchPath, parseClapScan } from "./clap-loader.js";
|
|
29
29
|
import { HOSTING_CODE } from "./hosting-codes.js";
|
|
30
30
|
import { shippedHostProfile, type HostProfile } from "./host-profiles.js";
|
|
31
31
|
import { lv2BundlesOnPath, manifestPlugins } from "./lv2-loader.js";
|
|
32
|
-
import { judgmentPinEntries, pinsFile, type PinEntry } from "./pins-file.js";
|
|
32
|
+
import { judgmentPinEntries, pinClearLine, pinLineUri, pinsFile, type PinEntry } from "./pins-file.js";
|
|
33
|
+
import { POOL_RESULT, completePool, judgePoolRun, pinAfterPool, pinFromRecordWithPool, poolEnv, spawnedPoolRunner, type PoolRunner } from "./qualify-pool.js";
|
|
33
34
|
import { hostdPinFiles, type PinFilesRun } from "./hostd-pin-files.js";
|
|
34
35
|
import type { Judgment } from "./probe-judge.js";
|
|
35
36
|
import { qualifyTargets, type ProbeRun } from "./probe-runner.js";
|
|
36
37
|
import { GRID_FULL, parseGridSpec, type GridSpec } from "./measurement-grid.js";
|
|
37
38
|
import { adapterPass, type AdapterPassOptions, type AdapterPassResult } from "./qualify-adapter-pass.js";
|
|
38
39
|
import { ISOLATED_RESULT, baseSteps, completeIsolated, isolatedCell, missingSteps, judgeIsolatedRun, owesIsolated, pinAfterStep, spawnedIsolatedRunner, type IsolatedRunner } from "./qualify-isolated.js";
|
|
39
|
-
import { lv2World, rejudgeState, memoryPass, type MemoryPassResult, type RejudgeResult } from "./qualify-rejudge.js";
|
|
40
|
+
import { lv2World, rejudgeRecord, rejudgeState, rejudgeToolName, memoryPass, type MemoryPassResult, type RejudgeResult } from "./qualify-rejudge.js";
|
|
40
41
|
import { memoryBoundOf, parseMemoryLimit, type MemoryBound } from "./memory-bound.js";
|
|
41
|
-
import { rewriteRecord, writeQualification, type NotMeasured, type QualificationRecord } from "./qualification-record.js";
|
|
42
|
+
import { QUALIFICATION_RECORD_SCHEMA, latencyNeverTaken, rewriteRecord, writeQualification, type NotMeasured, type QualificationRecord } from "./qualification-record.js";
|
|
42
43
|
import { ADMIT_STEP_MS_ENV, DESCRIPTOR_DIR_STATE_SUBDIR, DESCRIPTOR_DIR_SYSTEM, MEMORY_PASS_PROBE_NOTES, QUALIFY_QUANTA, QUALIFY_RATES } from "./qualify-declarations.js";
|
|
43
44
|
import { toolsDir } from "./tool-paths.js";
|
|
44
45
|
import { writeFileWhole } from "./whole-file.js";
|
|
@@ -57,7 +58,7 @@ export const ZYNTHIAN_LV2_DIRS = ["/zynthian/zynthian-plugins/lv2", "/zynthian/z
|
|
|
57
58
|
export interface SyncSetting {
|
|
58
59
|
readonly key: string;
|
|
59
60
|
readonly meaning: string;
|
|
60
|
-
/** The default as `--help` and
|
|
61
|
+
/** The default as `--help` and docs/overview.md print it. */
|
|
61
62
|
readonly default: string;
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -142,6 +143,8 @@ export interface SyncArgs {
|
|
|
142
143
|
readonly adapterOnly: boolean;
|
|
143
144
|
/** `--isolated-only`: the missing isolated step of each record already judged, extending its run. */
|
|
144
145
|
readonly isolatedOnly: boolean;
|
|
146
|
+
/** `--pool-only`: the pool step of each CLAP record already judged that owes it, extending its run and giving its pin the word. */
|
|
147
|
+
readonly poolOnly: boolean;
|
|
145
148
|
readonly help: boolean;
|
|
146
149
|
/** The settings given as flags, by key. */
|
|
147
150
|
readonly values: ReadonlyMap<string, string>;
|
|
@@ -162,6 +165,7 @@ export function parseSyncArgs(argv: readonly string[]): { ok: true; args: SyncAr
|
|
|
162
165
|
let memoryOnly = false;
|
|
163
166
|
let adapterOnly = false;
|
|
164
167
|
let isolatedOnly = false;
|
|
168
|
+
let poolOnly = false;
|
|
165
169
|
let help = false;
|
|
166
170
|
for (let i = 0; i < argv.length; i++) {
|
|
167
171
|
const a = argv[i]!;
|
|
@@ -174,6 +178,7 @@ export function parseSyncArgs(argv: readonly string[]): { ok: true; args: SyncAr
|
|
|
174
178
|
else if (a === "--memory-only") memoryOnly = true;
|
|
175
179
|
else if (a === "--adapter-only") adapterOnly = true;
|
|
176
180
|
else if (a === "--isolated-only") isolatedOnly = true;
|
|
181
|
+
else if (a === "--pool-only") poolOnly = true;
|
|
177
182
|
else if (a === "--help") help = true;
|
|
178
183
|
else if (a === "--grid-hosts") values.set("grid", "hosts");
|
|
179
184
|
else if (a === "--config" || byFlag.has(a)) {
|
|
@@ -183,9 +188,9 @@ export function parseSyncArgs(argv: readonly string[]): { ok: true; args: SyncAr
|
|
|
183
188
|
else values.set(byFlag.get(a)!, v);
|
|
184
189
|
} else return { ok: false, error: `unknown argument ${a}` };
|
|
185
190
|
}
|
|
186
|
-
if (rejudge && (memoryOnly || adapterOnly || isolatedOnly || force || refreshPinsOnly)) return { ok: false, error: "--rejudge measures nothing: it goes with none of --memory-only, --adapter-only, --force and --refresh-pins" };
|
|
187
|
-
if ([memoryOnly, adapterOnly, isolatedOnly, refreshPinsOnly].filter(Boolean).length > 1) return { ok: false, error: "--memory-only, --adapter-only and --refresh-pins are different runs: one at a time" };
|
|
188
|
-
return { ok: true, args: { ...(config === undefined ? {} : { config }), system, force, noDistributed, noWait, refreshPins: refreshPinsOnly, rejudge, memoryOnly, adapterOnly, isolatedOnly, help, values } };
|
|
191
|
+
if (rejudge && (memoryOnly || adapterOnly || isolatedOnly || poolOnly || force || refreshPinsOnly)) return { ok: false, error: "--rejudge measures nothing: it goes with none of --memory-only, --adapter-only, --isolated-only, --pool-only, --force and --refresh-pins" };
|
|
192
|
+
if ([memoryOnly, adapterOnly, isolatedOnly, poolOnly, refreshPinsOnly].filter(Boolean).length > 1) return { ok: false, error: "--memory-only, --adapter-only, --isolated-only, --pool-only and --refresh-pins are different runs: one at a time" };
|
|
193
|
+
return { ok: true, args: { ...(config === undefined ? {} : { config }), system, force, noDistributed, noWait, refreshPins: refreshPinsOnly, rejudge, memoryOnly, adapterOnly, isolatedOnly, poolOnly, help, values } };
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
export function syncHelpText(): string {
|
|
@@ -202,6 +207,7 @@ export function syncHelpText(): string {
|
|
|
202
207
|
" --rejudge derive every record's verdicts, tiers and pin again from the figures it holds; measures nothing",
|
|
203
208
|
" --memory-only measure only the footprint of each recorded plugin at the Pi's cells and merge it; with --force, those already merged too",
|
|
204
209
|
" --isolated-only run only the isolated step each record still owes, adding it to the record's run",
|
|
210
|
+
" --pool-only run only the pool step each CLAP record still owes: a plugin that asks for the thread pool is run with it off and on, and its pin gets pool=cores or pool=off",
|
|
205
211
|
" --adapter-only run each LV2 plugin only under omx-clap-host's LV2 adapter at the Pi's cells, on private JACK servers, and merge it; with --force, those already done too",
|
|
206
212
|
" --grid-hosts the fast grid, the same as --grid hosts (7 cells with the shipped hosts)",
|
|
207
213
|
" --help this text",
|
|
@@ -522,6 +528,25 @@ export function machineReason(p: Pick<SyncPlugin, "outcome" | "code" | "detail">
|
|
|
522
528
|
return /wrote no document|cannot run the probe runner/.test(p.detail ?? "") ? "the measurement wrote no document" : undefined;
|
|
523
529
|
}
|
|
524
530
|
|
|
531
|
+
/**
|
|
532
|
+
* The figure the records of a recorded entry never took, or `undefined`: a record whose probe ran before that figure's
|
|
533
|
+
* pass ({@link latencyNeverTaken}) owes a measurement, and the sync measures the entry again although its bytes are the
|
|
534
|
+
* ones it recorded. A record that cannot be read owes nothing here: the sync's other checks deal with it.
|
|
535
|
+
*/
|
|
536
|
+
export function figureOwed(entry: Pick<SyncEntry, "plugins">): "latency" | undefined {
|
|
537
|
+
for (const p of entry.plugins) {
|
|
538
|
+
if (p.record === undefined) continue;
|
|
539
|
+
let r: QualificationRecord;
|
|
540
|
+
try {
|
|
541
|
+
r = JSON.parse(readFileSync(p.record, "utf8")) as QualificationRecord;
|
|
542
|
+
} catch {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (r.schema === QUALIFICATION_RECORD_SCHEMA && latencyNeverTaken(r)) return "latency";
|
|
546
|
+
}
|
|
547
|
+
return undefined;
|
|
548
|
+
}
|
|
549
|
+
|
|
525
550
|
/** What the quick qualification never measures, stated in every record it writes. */
|
|
526
551
|
export const QUICK_NOT_MEASURED: readonly NotMeasured[] = [{ dimension: "stability", code: HOSTING_CODE.stabilityUnsoaked }];
|
|
527
552
|
|
|
@@ -621,6 +646,8 @@ export interface SyncContext {
|
|
|
621
646
|
readonly pinFilesRun?: PinFilesRun;
|
|
622
647
|
/** The isolated step, a stand-in in tests. */
|
|
623
648
|
readonly isolatedRunner?: IsolatedRunner;
|
|
649
|
+
/** The pool step, a stand-in in tests. */
|
|
650
|
+
readonly poolRunner?: PoolRunner;
|
|
624
651
|
}
|
|
625
652
|
|
|
626
653
|
/**
|
|
@@ -708,10 +735,10 @@ function writeUnmeasuredRecord(ctx: SyncContext, item: SyncItem, files: readonly
|
|
|
708
735
|
const isolatedEnv = (ctx: SyncContext): Readonly<Record<string, string | undefined>> => ({ ...ctx.env, [ADMIT_STEP_MS_ENV]: String(ctx.settings.budgetS * 1000) });
|
|
709
736
|
|
|
710
737
|
/** Each judged run of a pass as the plugins it qualified: the record written, the pin taken, the outcome. */
|
|
711
|
-
function judgedPlugins(ctx: SyncContext, runs: readonly { bytes: Buffer; judgment: Judgment }[], describeProblem?: string): SyncPlugin[] {
|
|
738
|
+
function judgedPlugins(ctx: SyncContext, runs: readonly { bytes: Buffer; judgment: Judgment; stderr?: readonly Buffer[] }[], describeProblem?: string): SyncPlugin[] {
|
|
712
739
|
const host = ctx.settings.hostProfile.id;
|
|
713
|
-
const entries = runs.map(({ bytes, judgment }) => {
|
|
714
|
-
const { recordPath, record } = writeQualification(ctx.settings.qualificationDir, bytes, judgment, QUICK_NOT_MEASURED);
|
|
740
|
+
const entries = runs.map(({ bytes, judgment, stderr }) => {
|
|
741
|
+
const { recordPath, record } = writeQualification(ctx.settings.qualificationDir, bytes, judgment, QUICK_NOT_MEASURED, stderr);
|
|
715
742
|
const steps = baseSteps(record, describeProblem);
|
|
716
743
|
let pin = withHostdFiles(ctx, judgmentPinEntries(judgment, host)[0]);
|
|
717
744
|
let { outcome, code } = outcomeOf(judgment, host);
|
|
@@ -738,6 +765,13 @@ function judgedPlugins(ctx: SyncContext, runs: readonly { bytes: Buffer; judgmen
|
|
|
738
765
|
code = undefined;
|
|
739
766
|
}
|
|
740
767
|
}
|
|
768
|
+
// the pool is for a CLAP plugin that runs: the thread pool is granted by measuring it, here and nowhere else
|
|
769
|
+
if (judgment.output.plugin.format === "clap" && pin !== undefined && pin.verdict !== "refused" && outcome === "qualified") {
|
|
770
|
+
const runner = ctx.poolRunner ?? spawnedPoolRunner();
|
|
771
|
+
const step = judgePoolRun(runner(pin.uri, isolatedCell(record, host), poolEnv(ctx.env, ctx.settings.budgetS)));
|
|
772
|
+
steps.push(step);
|
|
773
|
+
pin = pinAfterPool(pin, step);
|
|
774
|
+
}
|
|
741
775
|
rewriteRecord(recordPath, { ...record, run: { id: judgment.output.run.id, steps } });
|
|
742
776
|
const plugin: SyncPlugin = { uri: pin?.uri ?? judgment.output.plugin.id, outcome, ...(code === undefined ? {} : { code }), ...(pin === undefined ? {} : { pin }), record: recordPath };
|
|
743
777
|
return { plugin, judgedHere: judgment.hosts.some((h) => h.verdict.host === host) };
|
|
@@ -866,8 +900,8 @@ export function qualifyItem(ctx: SyncContext, item: SyncItem, files: readonly Fi
|
|
|
866
900
|
* The isolated steps the records of a state still owe, each extending its record's run. A plugin's pin follows its step, and
|
|
867
901
|
* a step that could not run stays owed: the next pass tries it again.
|
|
868
902
|
*/
|
|
869
|
-
export function isolatedPass(ctx: SyncContext, state: SyncState): { readonly state: SyncState; readonly isolated: number; readonly refused: number; readonly notRun: number } {
|
|
870
|
-
const count = { isolated: 0, refused: 0, notRun: 0 };
|
|
903
|
+
export function isolatedPass(ctx: SyncContext, state: SyncState): { readonly state: SyncState; readonly isolated: number; readonly refused: number; readonly notRun: number; readonly repinned: number } {
|
|
904
|
+
const count = { isolated: 0, refused: 0, notRun: 0, repinned: 0 };
|
|
871
905
|
const runner = ctx.isolatedRunner ?? spawnedIsolatedRunner();
|
|
872
906
|
const host = ctx.settings.hostProfile.id;
|
|
873
907
|
const entries: Record<string, SyncEntry> = {};
|
|
@@ -885,7 +919,17 @@ export function isolatedPass(ctx: SyncContext, state: SyncState): { readonly sta
|
|
|
885
919
|
return p;
|
|
886
920
|
}
|
|
887
921
|
const done = completeIsolated(path, record, p.pin?.uri ?? record.plugin.id, isolatedCell(record, host), runner, isolatedEnv(ctx));
|
|
888
|
-
if (done === undefined)
|
|
922
|
+
if (done === undefined) {
|
|
923
|
+
// a plugin the isolated step already decided but the state holds no pin for: the record keeps the bytes and the
|
|
924
|
+
// step, and the pin follows them (hostd names the files, as at every other pin)
|
|
925
|
+
if (p.pin !== undefined) return p;
|
|
926
|
+
const rebuilt = withHostdFiles(ctx, pinFromRecordWithPool(record));
|
|
927
|
+
if (rebuilt === undefined) return p;
|
|
928
|
+
count.repinned++;
|
|
929
|
+
ctx.log(`${p.uri}: pinned again from its record (isolated step ${rebuilt.verdict ?? "undecided"})`);
|
|
930
|
+
const { code: _c, ...rest } = p;
|
|
931
|
+
return rest.outcome === "qualified" && rebuilt.verdict === "refused" ? { ...rest, outcome: "refused" as const, pin: rebuilt } : { ...rest, pin: rebuilt };
|
|
932
|
+
}
|
|
889
933
|
ctx.log(`${p.uri}: isolated step ${done.step.result}${done.step.code === undefined ? "" : ` (${done.step.code})`}`);
|
|
890
934
|
const pin = pinAfterStep(p.pin, done.step);
|
|
891
935
|
const { pin: _pin, code: _code, ...rest } = p;
|
|
@@ -899,7 +943,44 @@ export function isolatedPass(ctx: SyncContext, state: SyncState): { readonly sta
|
|
|
899
943
|
}),
|
|
900
944
|
};
|
|
901
945
|
}
|
|
902
|
-
return { ...count, state: count.isolated + count.refused + count.notRun === 0 ? state : { ...state, entries } };
|
|
946
|
+
return { ...count, state: count.isolated + count.refused + count.notRun + count.repinned === 0 ? state : { ...state, entries } };
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* The pool steps the CLAP records of a state still owe, each extending its record's run. A plugin's pin takes the pool word
|
|
951
|
+
* of its step (`cores`, or `off` for a plugin that was measured and gains nothing) and none for a plugin that does not ask
|
|
952
|
+
* for the pool. A step that could not run stays owed: the next pass tries it again.
|
|
953
|
+
*/
|
|
954
|
+
export function poolPass(ctx: SyncContext, state: SyncState): { readonly state: SyncState; readonly cores: number; readonly off: number; readonly notAsked: number; readonly notRun: number } {
|
|
955
|
+
const count = { cores: 0, off: 0, notAsked: 0, notRun: 0 };
|
|
956
|
+
const runner = ctx.poolRunner ?? spawnedPoolRunner();
|
|
957
|
+
const host = ctx.settings.hostProfile.id;
|
|
958
|
+
const entries: Record<string, SyncEntry> = {};
|
|
959
|
+
for (const [key, entry] of Object.entries(state.entries)) {
|
|
960
|
+
entries[key] = {
|
|
961
|
+
...entry,
|
|
962
|
+
plugins: entry.plugins.map((p) => {
|
|
963
|
+
if (p.record === undefined || !p.record.endsWith(".qualification.json") || p.pin === undefined || p.pin.verdict === "refused") return p;
|
|
964
|
+
const path = join(ctx.settings.qualificationDir, basename(p.record));
|
|
965
|
+
let record: QualificationRecord;
|
|
966
|
+
try {
|
|
967
|
+
record = JSON.parse(readFileSync(path, "utf8")) as QualificationRecord;
|
|
968
|
+
} catch {
|
|
969
|
+
ctx.log(`${p.uri}: its record does not read; no pool step`);
|
|
970
|
+
return p;
|
|
971
|
+
}
|
|
972
|
+
const done = completePool(path, record, p.pin.uri, isolatedCell(record, host), runner, poolEnv(ctx.env, ctx.settings.budgetS));
|
|
973
|
+
if (done === undefined) return p;
|
|
974
|
+
ctx.log(`${p.uri}: pool step ${done.step.result}${done.step.code === undefined ? "" : ` (${done.step.code})`}`);
|
|
975
|
+
if (done.step.result === POOL_RESULT.cores) count.cores++;
|
|
976
|
+
else if (done.step.result === POOL_RESULT.off) count.off++;
|
|
977
|
+
else if (done.step.result === POOL_RESULT.notAsked) count.notAsked++;
|
|
978
|
+
else count.notRun++;
|
|
979
|
+
return { ...p, pin: pinAfterPool(p.pin, done.step)! };
|
|
980
|
+
}),
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
return { ...count, state: count.cores + count.off + count.notAsked + count.notRun === 0 ? state : { ...state, entries } };
|
|
903
984
|
}
|
|
904
985
|
|
|
905
986
|
// --- the distributed records ----------------------------------------------------------------------------------------
|
|
@@ -938,10 +1019,35 @@ function takeDistributed(ctx: SyncContext, layer: DistributedLayer, item: SyncIt
|
|
|
938
1019
|
ctx.log(`distributed: ${distributedUri(item, r)}: its record lacks the step${missing.length === 1 ? "" : "s"} ${missing.join(", ")}; measured here`);
|
|
939
1020
|
return undefined;
|
|
940
1021
|
}
|
|
1022
|
+
if (latencyNeverTaken(r.record)) {
|
|
1023
|
+
ctx.log(`distributed: ${distributedUri(item, r)}: its record never took the latency figure (a probe from before that pass); measured here`);
|
|
1024
|
+
return undefined;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
// The set was judged by the plugin-qualify that measured it. Its figures are carried across and judged again under
|
|
1028
|
+
// today's rules, as an upgrade's are (`--rejudge`): a verdict of an older judge (RT-unsafe read as refused, before
|
|
1029
|
+
// #196) is never taken as it stands. A record today's judge cannot decide for this host is measured here.
|
|
1030
|
+
const by = rejudgeToolName();
|
|
1031
|
+
const at = new Date(started).toISOString();
|
|
1032
|
+
const records = [];
|
|
1033
|
+
for (const r of match.records) {
|
|
1034
|
+
let record: QualificationRecord;
|
|
1035
|
+
try {
|
|
1036
|
+
record = rejudgeRecord(r.record, readFileSync(join(r.path, "..", r.record.probe.file)), { host, by, at }).record;
|
|
1037
|
+
} catch (e) {
|
|
1038
|
+
ctx.log(`distributed: ${distributedUri(item, r)}: ${(e as Error).message}; measured here`);
|
|
1039
|
+
return undefined;
|
|
1040
|
+
}
|
|
1041
|
+
const v = record.verdicts.find((x) => x.host === host);
|
|
1042
|
+
if (v !== undefined && outcomeOfVerdict(v) === "unmeasured") {
|
|
1043
|
+
ctx.log(`distributed: ${distributedUri(item, r)}: judged again, ${v.deciding ?? "unknown"} for ${host}; measured here`);
|
|
1044
|
+
return undefined;
|
|
1045
|
+
}
|
|
1046
|
+
records.push({ ...r, record });
|
|
941
1047
|
}
|
|
942
1048
|
let plugins: SyncPlugin[];
|
|
943
1049
|
try {
|
|
944
|
-
plugins = applyDistributed(ctx.settings.qualificationDir, item, match, host);
|
|
1050
|
+
plugins = applyDistributed(ctx.settings.qualificationDir, item, { ...match, records }, host);
|
|
945
1051
|
} catch (e) {
|
|
946
1052
|
ctx.log(`distributed: ${distributedUri(item, match.records[0]!)}: ${(e as Error).message}; measured here`);
|
|
947
1053
|
return undefined;
|
|
@@ -980,7 +1086,7 @@ export function syncPinsText(state: SyncState): string {
|
|
|
980
1086
|
/** The pin lines, by uri. */
|
|
981
1087
|
function pinLinesOf(text: string): Map<string, string> {
|
|
982
1088
|
const out = new Map<string, string>();
|
|
983
|
-
for (const line of text.split("\n")) if (line !== "" && !line.startsWith("#")) out.set(line
|
|
1089
|
+
for (const line of text.split("\n")) if (line !== "" && !line.startsWith("#")) out.set(pinLineUri(line)!, line);
|
|
984
1090
|
return out;
|
|
985
1091
|
}
|
|
986
1092
|
|
|
@@ -996,9 +1102,9 @@ export function removedPinUris(before: string, after: string): string[] {
|
|
|
996
1102
|
return [...pinLinesOf(before).keys()].filter((uri) => !now.has(uri));
|
|
997
1103
|
}
|
|
998
1104
|
|
|
999
|
-
/** `<id>@<version>-<binary sha first 12>`, the stem a qualification record, its probe copy and its descriptor share. */
|
|
1105
|
+
/** `<id>@<version>-<binary sha first 12>`, the stem a qualification record, its probe copy, its children's stderr and its descriptor share. */
|
|
1000
1106
|
export function recordStem(recordPath: string): string | undefined {
|
|
1001
|
-
return /^(.*-[0-9a-f]{12})\.(?:[^.]+\.(?:qualification|probe)|unmeasured)\.json$/.exec(basename(recordPath))?.[1];
|
|
1107
|
+
return /^(.*-[0-9a-f]{12})\.(?:(?:[^.]+\.(?:qualification|probe)|unmeasured)\.json|[^.]+\.stderr\.[0-9a-f]{12}\.log)$/.exec(basename(recordPath))?.[1];
|
|
1002
1108
|
}
|
|
1003
1109
|
|
|
1004
1110
|
/**
|
|
@@ -1181,6 +1287,8 @@ export interface SyncSummary {
|
|
|
1181
1287
|
readonly machineFailure?: string;
|
|
1182
1288
|
/** `--isolated-only`: how the steps ended. */
|
|
1183
1289
|
readonly isolatedOnly?: { readonly isolated: number; readonly refused: number; readonly notRun: number };
|
|
1290
|
+
/** `--pool-only`: the plugins granted the thread pool, those measured and not granted it, those that do not ask for it, and those the step could not run for. */
|
|
1291
|
+
readonly poolOnly?: { readonly cores: number; readonly off: number; readonly notAsked: number; readonly notRun: number };
|
|
1184
1292
|
/** `--adapter-only`: the plugins run, those done already at these host versions, and those whose host could not be run. */
|
|
1185
1293
|
readonly adapterOnly?: { readonly measured: number; readonly already: number; readonly failed: number };
|
|
1186
1294
|
}
|
|
@@ -1266,7 +1374,7 @@ export function pluginCountsLine(c: PluginCounts): string {
|
|
|
1266
1374
|
}
|
|
1267
1375
|
|
|
1268
1376
|
export function summaryLine(s: SyncSummary): string {
|
|
1269
|
-
return `qualified ${String(s.qualified)}, skipped ${String(s.skipped)}, refused ${String(s.refused)}, crashed ${String(s.crashed)}, hung ${String(s.hung)}, unmeasured ${String(s.unmeasured)}, distributed ${String(s.distributed)}${s.refreshed ? `, pins refreshed ${String(s.refreshed)}` : ""}${s.rejudge === undefined ? "" : `, rejudged ${String(s.rejudge.changed)}, unchanged ${String(s.rejudge.unchanged)}, owing ${String(s.rejudge.owing)}`}${s.memoryOnly === undefined ? "" : `, memory measured ${String(s.memoryOnly.measured)}, already ${String(s.memoryOnly.already)}, failed ${String(s.memoryOnly.failed)}, leaks not measured`}${s.adapterOnly === undefined ? "" : `, adapter run ${String(s.adapterOnly.measured)}, already ${String(s.adapterOnly.already)}, failed ${String(s.adapterOnly.failed)}`}, ${s.seconds.toFixed(1)} s`;
|
|
1377
|
+
return `qualified ${String(s.qualified)}, skipped ${String(s.skipped)}, refused ${String(s.refused)}, crashed ${String(s.crashed)}, hung ${String(s.hung)}, unmeasured ${String(s.unmeasured)}, distributed ${String(s.distributed)}${s.refreshed ? `, pins refreshed ${String(s.refreshed)}` : ""}${s.rejudge === undefined ? "" : `, rejudged ${String(s.rejudge.changed)}, unchanged ${String(s.rejudge.unchanged)}, owing ${String(s.rejudge.owing)}`}${s.memoryOnly === undefined ? "" : `, memory measured ${String(s.memoryOnly.measured)}, already ${String(s.memoryOnly.already)}, failed ${String(s.memoryOnly.failed)}, leaks not measured`}${s.poolOnly === undefined ? "" : `, pool granted ${String(s.poolOnly.cores)}, off ${String(s.poolOnly.off)}, not asked ${String(s.poolOnly.notAsked)}, not run ${String(s.poolOnly.notRun)}`}${s.adapterOnly === undefined ? "" : `, adapter run ${String(s.adapterOnly.measured)}, already ${String(s.adapterOnly.already)}, failed ${String(s.adapterOnly.failed)}`}, ${s.seconds.toFixed(1)} s`;
|
|
1270
1378
|
}
|
|
1271
1379
|
|
|
1272
1380
|
/** The exit status `flock -n` returns when the lock is held (-E), told apart from a failure of flock itself. */
|
|
@@ -1320,6 +1428,10 @@ export interface SyncRunOptions {
|
|
|
1320
1428
|
readonly isolatedRunner?: IsolatedRunner;
|
|
1321
1429
|
/** `--isolated-only`: take only the isolated steps records still owe. */
|
|
1322
1430
|
readonly isolatedOnly?: boolean;
|
|
1431
|
+
/** The pool step, a stand-in in tests. */
|
|
1432
|
+
readonly poolRunner?: PoolRunner;
|
|
1433
|
+
/** `--pool-only`: take only the pool steps records still owe. */
|
|
1434
|
+
readonly poolOnly?: boolean;
|
|
1323
1435
|
/** `--adapter-only`: take only the adapter runs; `force` takes those already done again. */
|
|
1324
1436
|
readonly adapterOnly?: boolean;
|
|
1325
1437
|
/** Stand-ins for the pass's hosts, in tests. */
|
|
@@ -1388,6 +1500,7 @@ function addSummaries(a: SyncSummary, b: SyncSummary): SyncSummary {
|
|
|
1388
1500
|
...(b.rejudge === undefined ? (a.rejudge === undefined ? {} : { rejudge: a.rejudge }) : { rejudge: b.rejudge }),
|
|
1389
1501
|
...(b.memoryOnly === undefined ? (a.memoryOnly === undefined ? {} : { memoryOnly: a.memoryOnly }) : { memoryOnly: b.memoryOnly }),
|
|
1390
1502
|
...(b.isolatedOnly === undefined ? (a.isolatedOnly === undefined ? {} : { isolatedOnly: a.isolatedOnly }) : { isolatedOnly: b.isolatedOnly }),
|
|
1503
|
+
...(b.poolOnly === undefined ? (a.poolOnly === undefined ? {} : { poolOnly: a.poolOnly }) : { poolOnly: b.poolOnly }),
|
|
1391
1504
|
...(b.adapterOnly === undefined ? (a.adapterOnly === undefined ? {} : { adapterOnly: a.adapterOnly }) : { adapterOnly: b.adapterOnly }),
|
|
1392
1505
|
};
|
|
1393
1506
|
}
|
|
@@ -1413,7 +1526,7 @@ async function runLocked(settings: SyncSettings, options: SyncRunOptions): Promi
|
|
|
1413
1526
|
{
|
|
1414
1527
|
const started = Date.now();
|
|
1415
1528
|
const dirs = [...settings.clapDirs, ...settings.lv2Dirs];
|
|
1416
|
-
const ctx: SyncContext = { settings, env, log, ...(options.pinFilesRun === undefined ? {} : { pinFilesRun: options.pinFilesRun }), ...(options.isolatedRunner === undefined ? {} : { isolatedRunner: options.isolatedRunner }) };
|
|
1529
|
+
const ctx: SyncContext = { settings, env, log, ...(options.pinFilesRun === undefined ? {} : { pinFilesRun: options.pinFilesRun }), ...(options.isolatedRunner === undefined ? {} : { isolatedRunner: options.isolatedRunner }), ...(options.poolRunner === undefined ? {} : { poolRunner: options.poolRunner }) };
|
|
1417
1530
|
// the pins first, before the quiet wait and any measurement: an upgrade of plugin-hostd that collects more files
|
|
1418
1531
|
// than the pins on disk hold refuses those plugins until their pins name them (plugin-qualify#239)
|
|
1419
1532
|
const fresh = refreshPins(ctx, readSyncState(settings.stateFile, log));
|
|
@@ -1433,6 +1546,12 @@ async function runLocked(settings: SyncSettings, options: SyncRunOptions): Promi
|
|
|
1433
1546
|
const summary = await sendRefreshed(settings, r.state, fresh.refreshed.length, started, log);
|
|
1434
1547
|
return { ...summary, isolatedOnly: { isolated: r.isolated, refused: r.refused, notRun: r.notRun } };
|
|
1435
1548
|
}
|
|
1549
|
+
if (options.poolOnly === true) {
|
|
1550
|
+
const r = poolPass(ctx, fresh.state);
|
|
1551
|
+
if (r.state !== fresh.state) writeFileWhole(settings.stateFile, `${JSON.stringify(r.state, null, 1)}\n`);
|
|
1552
|
+
const summary = await sendRefreshed(settings, r.state, fresh.refreshed.length, started, log);
|
|
1553
|
+
return { ...summary, poolOnly: { cores: r.cores, off: r.off, notAsked: r.notAsked, notRun: r.notRun } };
|
|
1554
|
+
}
|
|
1436
1555
|
if (options.adapterOnly === true) {
|
|
1437
1556
|
const r: AdapterPassResult = adapterPass(ctx, fresh.state, { ...options.adapterPass, force: options.force === true });
|
|
1438
1557
|
log(`adapter runs under ${Object.entries(r.versions).map(([k, v]) => `${k} ${v}`).join(", ")}`);
|
|
@@ -1480,7 +1599,8 @@ async function runLocked(settings: SyncSettings, options: SyncRunOptions): Promi
|
|
|
1480
1599
|
for (const item of items) {
|
|
1481
1600
|
const recorded = recordedAsIs(item, entries[item.key]);
|
|
1482
1601
|
const retry = recorded.same ? entries[item.key]!.plugins.map(machineReason).find((r) => r !== undefined) : undefined;
|
|
1483
|
-
|
|
1602
|
+
const owed = recorded.same && options.force !== true && retry === undefined ? figureOwed(entries[item.key]!) : undefined;
|
|
1603
|
+
if (recorded.same && options.force !== true && retry === undefined && owed === undefined) {
|
|
1484
1604
|
if (pass === 0) count.skipped += entries[item.key]!.plugins.length;
|
|
1485
1605
|
continue;
|
|
1486
1606
|
}
|
|
@@ -1498,6 +1618,7 @@ async function runLocked(settings: SyncSettings, options: SyncRunOptions): Promi
|
|
|
1498
1618
|
continue;
|
|
1499
1619
|
}
|
|
1500
1620
|
if (recorded.same && retry !== undefined) log(`${item.key}: unmeasured last run by the machine (${retry}); measured again`);
|
|
1621
|
+
if (owed !== undefined) log(`${item.key}: its record never took the ${owed} figure (a probe from before that pass); measured again`);
|
|
1501
1622
|
const files = recorded.files ?? digestFiles(item.root, item.files);
|
|
1502
1623
|
if (files === undefined) {
|
|
1503
1624
|
log(`${item.key}: a file of it cannot be read; skipped this run`);
|
|
@@ -1544,7 +1665,7 @@ async function runLocked(settings: SyncSettings, options: SyncRunOptions): Promi
|
|
|
1544
1665
|
if (unreadable) log("a plugin directory could not be read; no record or descriptor is removed this run");
|
|
1545
1666
|
else for (const f of pruneStale(settings, stateBefore, state)) log(`${f}: removed, its plugin is gone or changed`);
|
|
1546
1667
|
// a plugin that was pinned and is not any more is also forgotten by a running daemon
|
|
1547
|
-
const changed = [...changedPinLines(before, after), ...removedPinUris(before, after).map(
|
|
1668
|
+
const changed = [...changedPinLines(before, after), ...removedPinUris(before, after).map(pinClearLine)];
|
|
1548
1669
|
const sent = await sendPins(settings.hostdPort, settings.hostdFeedbackPort, changed);
|
|
1549
1670
|
if ("unsent" in sent) {
|
|
1550
1671
|
const why = {
|
|
@@ -1555,7 +1676,7 @@ async function runLocked(settings: SyncSettings, options: SyncRunOptions): Promi
|
|
|
1555
1676
|
log(`${why}; the ${String(changed.length)} changed pins apply at its next start, from the pin file`);
|
|
1556
1677
|
}
|
|
1557
1678
|
const replies = "replies" in sent ? sent.replies : [];
|
|
1558
|
-
for (let i = 0; i < replies.length; i++) if (replies[i] !== "resp 0") log(`plugin-hostd answered ${replies[i]!} to ${changed[i]
|
|
1679
|
+
for (let i = 0; i < replies.length; i++) if (replies[i] !== "resp 0") log(`plugin-hostd answered ${replies[i]!} to ${pinLineUri(changed[i]!)!}`);
|
|
1559
1680
|
const taken = replies.filter((r) => r === "resp 0").length;
|
|
1560
1681
|
for (const [why, n] of byMachine) if (n > 1) log(`${String(n)} plugins unmeasured by the machine (${why}); the first is listed above`);
|
|
1561
1682
|
const [only] = byMachine.size === 1 ? [...byMachine] : [];
|
package/src/records-package.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* `plugin-qualify-records-package`: the Debian package of a device's qualification records, so other devices of the
|
|
5
5
|
* machine class install them as the distributed layer instead of measuring the same plugin set again.
|
|
6
6
|
*
|
|
7
|
-
* In: a qualification directory as plugin-qualify-sync leaves it. Out: `
|
|
7
|
+
* In: a qualification directory as plugin-qualify-sync leaves it. Out: `plugin-db-qualification-<class>-<set>_<version>_all.deb`,
|
|
8
|
+
* a package of plugin-db's qualification layer,
|
|
8
9
|
* installing every record and the probe output it judged under `/usr/share/omx/qualification/<class>/<set>/`, beside
|
|
9
10
|
* the set's `provenance.json`. A record goes in only with its probe output, byte for byte the copy the record names;
|
|
10
11
|
* an unmeasured record never applies and stays out. The archive is written here, `ar` and two `tar.xz` members, so a
|
|
@@ -16,7 +17,7 @@ import { closeSync, copyFileSync, mkdirSync, mkdtempSync, openSync, readFileSync
|
|
|
16
17
|
import { tmpdir } from "node:os";
|
|
17
18
|
import { join } from "node:path";
|
|
18
19
|
|
|
19
|
-
import { DISTRIBUTED_DIR_SYSTEM,
|
|
20
|
+
import { DISTRIBUTED_DIR_SYSTEM, DISTRIBUTED_PROVENANCE_FILE, DISTRIBUTED_PROVENANCE_SCHEMA, type DistributedProvenance } from "./distributed-records.js";
|
|
20
21
|
import { sha256Hex } from "./probe-output.js";
|
|
21
22
|
import { QUALIFICATION_RECORD_SCHEMA } from "./qualification-record.js";
|
|
22
23
|
|
|
@@ -53,7 +54,7 @@ export function recordsPackageHelp(): string {
|
|
|
53
54
|
" --maintainer <who> the package's Maintainer field",
|
|
54
55
|
" --help this text",
|
|
55
56
|
"",
|
|
56
|
-
`the package installs ${DISTRIBUTED_DIR_SYSTEM}/<class>/<set>/ and depends on plugin-qualify
|
|
57
|
+
`the package installs ${DISTRIBUTED_DIR_SYSTEM}/<class>/<set>/ and depends on this plugin-qualify's minor, up to the next one`,
|
|
57
58
|
"exit 0 the package was written, 2 it could not be",
|
|
58
59
|
"",
|
|
59
60
|
].join("\n");
|
|
@@ -97,7 +98,21 @@ export function parseRecordsPackageArgs(argv: readonly string[]): { ok: true; ar
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/** The package of a class and a set. */
|
|
100
|
-
export const recordsPackageName = (hostClass: string, set: string): string => `
|
|
101
|
+
export const recordsPackageName = (hostClass: string, set: string): string => `plugin-db-qualification-${hostClass}-${set}`;
|
|
102
|
+
|
|
103
|
+
/** The plugin-qualify a package of records depends on: the minor that wrote them, up to the next minor. */
|
|
104
|
+
export function recordsDependsRange(version: string): { floor: string; ceiling: string } | undefined {
|
|
105
|
+
const m = /^(\d+)\.(\d+)\.\d+/.exec(version);
|
|
106
|
+
if (m === null) return undefined;
|
|
107
|
+
const major = Number(m[1]);
|
|
108
|
+
const minor = Number(m[2]);
|
|
109
|
+
return { floor: `${String(major)}.${String(minor)}.0`, ceiling: `${String(major)}.${String(minor + 1)}` };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** This plugin-qualify's own version, read where it is installed. */
|
|
113
|
+
function ownVersion(): string {
|
|
114
|
+
return (JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as { version?: string }).version ?? "";
|
|
115
|
+
}
|
|
101
116
|
|
|
102
117
|
/** Today as a package version, `2026.10.29`, and as a date, `2026-10-29`, in local time. */
|
|
103
118
|
export function today(now = new Date()): { version: string; date: string } {
|
|
@@ -199,6 +214,8 @@ export interface BuiltRecordsPackage {
|
|
|
199
214
|
/** The package of `args`, written into `args.out`. Throws, naming why, when it cannot be built. */
|
|
200
215
|
export function buildRecordsPackage(args: RecordsPackageArgs, now = new Date()): BuiltRecordsPackage {
|
|
201
216
|
const name = recordsPackageName(args.hostClass, args.set);
|
|
217
|
+
const range = recordsDependsRange(ownVersion());
|
|
218
|
+
if (range === undefined) throw new Error("this plugin-qualify names no version, so the package cannot say which one reads it");
|
|
202
219
|
const day = today(now);
|
|
203
220
|
const version = args.version ?? day.version;
|
|
204
221
|
statSync(args.stateDir);
|
|
@@ -238,13 +255,13 @@ export function buildRecordsPackage(args: RecordsPackageArgs, now = new Date()):
|
|
|
238
255
|
"Architecture: all",
|
|
239
256
|
`Maintainer: ${args.maintainer}`,
|
|
240
257
|
`Installed-Size: ${String(kib)}`,
|
|
241
|
-
`Depends: plugin-qualify (>= ${
|
|
258
|
+
`Depends: plugin-qualify (>= ${range.floor}~), plugin-qualify (<< ${range.ceiling}~)`,
|
|
242
259
|
"Section: sound",
|
|
243
260
|
"Priority: optional",
|
|
244
261
|
"Multi-Arch: foreign",
|
|
245
|
-
`Description: qualification
|
|
246
|
-
` The
|
|
247
|
-
` ${args.hostClass} device. plugin-qualify-sync takes a plugin from them instead of`,
|
|
262
|
+
`Description: plugin-db qualification layer: ${args.set} set for ${args.hostClass}`,
|
|
263
|
+
` The qualification layer of the plugin database: the plugin-qualify records`,
|
|
264
|
+
` of the ${args.set} plugin set, measured on a ${args.hostClass} device. plugin-qualify-sync takes a plugin from them instead of`,
|
|
248
265
|
" measuring it, and only when every file of the installed plugin hashes as the",
|
|
249
266
|
" measured one did; any other plugin is measured on the device as before.",
|
|
250
267
|
"",
|
package/tools/benchmark.py
CHANGED
|
@@ -1201,7 +1201,9 @@ class _Host:
|
|
|
1201
1201
|
def __init__(self, rate, block):
|
|
1202
1202
|
import ctypes
|
|
1203
1203
|
|
|
1204
|
-
import
|
|
1204
|
+
from lilv_load import load_lilv
|
|
1205
|
+
|
|
1206
|
+
lilv = load_lilv()
|
|
1205
1207
|
|
|
1206
1208
|
self.urids = {}
|
|
1207
1209
|
|
|
@@ -1362,7 +1364,9 @@ def probe_one(host, uri, symbol, cycles=DEFAULT_RUN_CYCLES):
|
|
|
1362
1364
|
"""
|
|
1363
1365
|
import numpy as np
|
|
1364
1366
|
|
|
1365
|
-
import
|
|
1367
|
+
from lilv_load import load_lilv
|
|
1368
|
+
|
|
1369
|
+
lilv = load_lilv()
|
|
1366
1370
|
|
|
1367
1371
|
plugin = host.world.get_all_plugins().get_by_uri(host.world.new_uri(uri))
|
|
1368
1372
|
if plugin is None:
|
|
@@ -1453,7 +1457,9 @@ def instantiate_connected(host, plugin, overrides=None):
|
|
|
1453
1457
|
"""
|
|
1454
1458
|
import numpy as np
|
|
1455
1459
|
|
|
1456
|
-
import
|
|
1460
|
+
from lilv_load import load_lilv
|
|
1461
|
+
|
|
1462
|
+
lilv = load_lilv()
|
|
1457
1463
|
|
|
1458
1464
|
host.worker.reset()
|
|
1459
1465
|
instance = lilv.Instance(plugin, float(host.rate), host.features)
|