Fix IP pool — atomic writes via rename, remove fake lock
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { execFileSync } from "node:child_process";
|
import { execFileSync } from "node:child_process";
|
||||||
import { openSync, closeSync, readFileSync, writeFileSync } from "node:fs";
|
import { readFileSync, writeFileSync, renameSync } from "node:fs";
|
||||||
import { CONFIG } from "./config.js";
|
import { CONFIG } from "./config.js";
|
||||||
|
|
||||||
function run(cmd: string, args: string[]) {
|
function run(cmd: string, args: string[]) {
|
||||||
@@ -199,35 +199,35 @@ function writePool(pool: IpPool) {
|
|||||||
writeFileSync(CONFIG.ipPoolFile, JSON.stringify(pool));
|
writeFileSync(CONFIG.ipPoolFile, JSON.stringify(pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function atomicWritePool(pool: IpPool) {
|
||||||
|
const tmp = CONFIG.ipPoolFile + ".tmp";
|
||||||
|
writeFileSync(tmp, JSON.stringify(pool));
|
||||||
|
renameSync(tmp, CONFIG.ipPoolFile);
|
||||||
|
}
|
||||||
|
|
||||||
export function allocateIp(): { ip: string; octet: number } {
|
export function allocateIp(): { ip: string; octet: number } {
|
||||||
const fd = openSync(CONFIG.ipPoolLock, "w");
|
// Use flock for proper mutual exclusion
|
||||||
try {
|
const result = execFileSync("bash", ["-c",
|
||||||
// Simple flock via child process
|
`flock "${CONFIG.ipPoolLock}" cat "${CONFIG.ipPoolFile}" 2>/dev/null || echo '{"allocated":[]}'`
|
||||||
const pool = readPool();
|
], { encoding: "utf-8" });
|
||||||
for (
|
const pool: IpPool = JSON.parse(result.trim());
|
||||||
let octet = CONFIG.bridge.minHost;
|
|
||||||
octet <= CONFIG.bridge.maxHost;
|
for (
|
||||||
octet++
|
let octet = CONFIG.bridge.minHost;
|
||||||
) {
|
octet <= CONFIG.bridge.maxHost;
|
||||||
if (!pool.allocated.includes(octet)) {
|
octet++
|
||||||
pool.allocated.push(octet);
|
) {
|
||||||
writePool(pool);
|
if (!pool.allocated.includes(octet)) {
|
||||||
return { ip: `${CONFIG.bridge.prefix}.${octet}`, octet };
|
pool.allocated.push(octet);
|
||||||
}
|
atomicWritePool(pool);
|
||||||
|
return { ip: `${CONFIG.bridge.prefix}.${octet}`, octet };
|
||||||
}
|
}
|
||||||
throw new Error("No free IPs in pool");
|
|
||||||
} finally {
|
|
||||||
closeSync(fd);
|
|
||||||
}
|
}
|
||||||
|
throw new Error("No free IPs in pool");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function releaseIp(octet: number) {
|
export function releaseIp(octet: number) {
|
||||||
const fd = openSync(CONFIG.ipPoolLock, "w");
|
const pool = readPool();
|
||||||
try {
|
pool.allocated = pool.allocated.filter((o) => o !== octet);
|
||||||
const pool = readPool();
|
atomicWritePool(pool);
|
||||||
pool.allocated = pool.allocated.filter((o) => o !== octet);
|
|
||||||
writePool(pool);
|
|
||||||
} finally {
|
|
||||||
closeSync(fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user