Skip to content

Commit 8458477

Browse files
committed
btrfs: snapshot --> snapshots
1 parent 5e5e772 commit 8458477

File tree

8 files changed

+60
-60
lines changed

8 files changed

+60
-60
lines changed

src/packages/file-server/btrfs/filesystem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ a = require('@cocalc/file-server/storage-btrfs'); fs = await a.filesystem({devic
1414
import refCache from "@cocalc/util/refcache";
1515
import { exists, isdir, listdir, mkdirp, rmdir, sudo } from "./util";
1616
import { subvolume, type Subvolume } from "./subvolume";
17-
import { SNAPSHOTS } from "./subvolume-snapshot";
17+
import { SNAPSHOTS } from "./subvolume-snapshots";
1818
import { join, normalize } from "path";
1919

2020
// default size of btrfs filesystem if creating an image file.

src/packages/file-server/btrfs/snapshots.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type SubvolumeSnapshot } from "./subvolume-snapshot";
1+
import { type SubvolumeSnapshots } from "./subvolume-snapshots";
22
import getLogger from "@cocalc/backend/logger";
33

44
const logger = getLogger("file-server:storage-btrfs:snapshots");
@@ -30,17 +30,17 @@ export interface SnapshotCounts {
3030
}
3131

3232
export async function updateRollingSnapshots({
33-
snapshot,
33+
snapshots,
3434
counts,
3535
}: {
36-
snapshot: SubvolumeSnapshot;
36+
snapshots: SubvolumeSnapshots;
3737
counts?: Partial<SnapshotCounts>;
3838
}) {
3939
counts = { ...DEFAULT_SNAPSHOT_COUNTS, ...counts };
4040

41-
const changed = await snapshot.hasUnsavedChanges();
41+
const changed = await snapshots.hasUnsavedChanges();
4242
logger.debug("updateRollingSnapshots", {
43-
name: snapshot.subvolume.name,
43+
name: snapshots.subvolume.name,
4444
counts,
4545
changed,
4646
});
@@ -50,18 +50,18 @@ export async function updateRollingSnapshots({
5050
}
5151

5252
// get exactly the iso timestamp snapshot names:
53-
const snapshots = (await snapshot.ls())
53+
const snapshotNames = (await snapshots.ls())
5454
.map((x) => x.name)
5555
.filter((name) => DATE_REGEXP.test(name));
56-
snapshots.sort();
57-
if (snapshots.length > 0) {
58-
const age = Date.now() - new Date(snapshots.slice(-1)[0]).valueOf();
56+
snapshotNames.sort();
57+
if (snapshotNames.length > 0) {
58+
const age = Date.now() - new Date(snapshotNames.slice(-1)[0]).valueOf();
5959
for (const key in SNAPSHOT_INTERVALS_MS) {
6060
if (counts[key]) {
6161
if (age < SNAPSHOT_INTERVALS_MS[key]) {
6262
// no need to snapshot since there is already a sufficiently recent snapshot
6363
logger.debug("updateRollingSnapshots: no need to snapshot", {
64-
name: snapshot.subvolume.name,
64+
name: snapshots.subvolume.name,
6565
});
6666
return;
6767
}
@@ -73,13 +73,13 @@ export async function updateRollingSnapshots({
7373

7474
// make a new snapshot
7575
const name = new Date().toISOString();
76-
await snapshot.create(name);
76+
await snapshots.create(name);
7777
// delete extra snapshots
78-
snapshots.push(name);
79-
const toDelete = snapshotsToDelete({ counts, snapshots });
78+
snapshotNames.push(name);
79+
const toDelete = snapshotsToDelete({ counts, snapshots: snapshotNames });
8080
for (const expired of toDelete) {
8181
try {
82-
await snapshot.delete(expired);
82+
await snapshots.delete(expired);
8383
} catch {
8484
// some snapshots can't be deleted, e.g., they were used for the last send.
8585
}

src/packages/file-server/btrfs/subvolume-bup.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ export class SubvolumeBup {
2323
// timeout used for bup index and bup save commands
2424
timeout = 30 * 60 * 1000,
2525
}: { timeout?: number } = {}) => {
26-
if (await this.subvolume.snapshot.exists(BUP_SNAPSHOT)) {
26+
if (await this.subvolume.snapshots.exists(BUP_SNAPSHOT)) {
2727
logger.debug(`createBupBackup: deleting existing ${BUP_SNAPSHOT}`);
28-
await this.subvolume.snapshot.delete(BUP_SNAPSHOT);
28+
await this.subvolume.snapshots.delete(BUP_SNAPSHOT);
2929
}
3030
try {
3131
logger.debug(
3232
`createBackup: creating ${BUP_SNAPSHOT} to get a consistent backup`,
3333
);
34-
await this.subvolume.snapshot.create(BUP_SNAPSHOT);
34+
await this.subvolume.snapshots.create(BUP_SNAPSHOT);
3535
const target = this.subvolume.normalize(
36-
this.subvolume.snapshot.path(BUP_SNAPSHOT),
36+
this.subvolume.snapshots.path(BUP_SNAPSHOT),
3737
);
3838

3939
logger.debug(`createBupBackup: indexing ${BUP_SNAPSHOT}`);
@@ -67,7 +67,7 @@ export class SubvolumeBup {
6767
});
6868
} finally {
6969
logger.debug(`createBupBackup: deleting temporary ${BUP_SNAPSHOT}`);
70-
await this.subvolume.snapshot.delete(BUP_SNAPSHOT);
70+
await this.subvolume.snapshots.delete(BUP_SNAPSHOT);
7171
}
7272
};
7373

@@ -78,7 +78,7 @@ export class SubvolumeBup {
7878
}
7979
path = normalize(path);
8080
// ... but to avoid potential data loss, we make a snapshot before deleting it.
81-
await this.subvolume.snapshot.create();
81+
await this.subvolume.snapshots.create();
8282
const i = path.indexOf("/"); // remove the commit name
8383
// remove the target we're about to restore
8484
await this.subvolume.fs.rm(path.slice(i + 1), { recursive: true });

src/packages/file-server/btrfs/subvolume-snapshot.ts renamed to src/packages/file-server/btrfs/subvolume-snapshots.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { type DirectoryListingEntry } from "@cocalc/util/types";
66
import { SnapshotCounts, updateRollingSnapshots } from "./snapshots";
77

88
export const SNAPSHOTS = ".snapshots";
9-
const logger = getLogger("file-server:storage-btrfs:subvolume-snapshot");
9+
const logger = getLogger("file-server:storage-btrfs:subvolume-snapshots");
1010

11-
export class SubvolumeSnapshot {
11+
export class SubvolumeSnapshots {
1212
public readonly snapshotsDir: string;
1313

1414
constructor(public subvolume: Subvolume) {
@@ -80,7 +80,7 @@ export class SubvolumeSnapshot {
8080

8181
// update the rolling snapshots schedule
8282
update = async (counts?: Partial<SnapshotCounts>) => {
83-
return await updateRollingSnapshots({ snapshot: this, counts });
83+
return await updateRollingSnapshots({ snapshots: this, counts });
8484
};
8585

8686
// has newly written changes since last snapshot

src/packages/file-server/btrfs/subvolume.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { exists, listdir, mkdirp, sudo } from "./util";
88
import { join, normalize } from "path";
99
import { SubvolumeFilesystem } from "./subvolume-fs";
1010
import { SubvolumeBup } from "./subvolume-bup";
11-
import { SubvolumeSnapshot } from "./subvolume-snapshot";
11+
import { SubvolumeSnapshots } from "./subvolume-snapshots";
1212
import getLogger from "@cocalc/backend/logger";
1313

1414
const SEND_SNAPSHOT_PREFIX = "send-";
@@ -28,15 +28,15 @@ export class Subvolume {
2828
public readonly path: string;
2929
public readonly fs: SubvolumeFilesystem;
3030
public readonly bup: SubvolumeBup;
31-
public readonly snapshot: SubvolumeSnapshot;
31+
public readonly snapshots: SubvolumeSnapshots;
3232

3333
constructor({ filesystem, name }: Options) {
3434
this.filesystem = filesystem;
3535
this.name = name;
3636
this.path = join(filesystem.opts.mount, name);
3737
this.fs = new SubvolumeFilesystem(this);
3838
this.bup = new SubvolumeBup(this);
39-
this.snapshot = new SubvolumeSnapshot(this);
39+
this.snapshots = new SubvolumeSnapshots(this);
4040
}
4141

4242
init = async () => {
@@ -187,7 +187,7 @@ export class Subvolume {
187187
const streams = new Set(
188188
await listdir(join(this.filesystem.streams, this.name)),
189189
);
190-
const allSnapshots = (await this.snapshot.ls()).map((x) => x.name);
190+
const allSnapshots = (await this.snapshots.ls()).map((x) => x.name);
191191
const snapshots = allSnapshots.filter(
192192
(x) => x.startsWith(SEND_SNAPSHOT_PREFIX) && streams.has(x),
193193
);
@@ -207,22 +207,22 @@ export class Subvolume {
207207
}
208208
const send = `${SEND_SNAPSHOT_PREFIX}${seq}`;
209209
if (allSnapshots.includes(send)) {
210-
await this.snapshot.delete(send);
210+
await this.snapshots.delete(send);
211211
}
212-
await this.snapshot.create(send);
212+
await this.snapshots.create(send);
213213
await sudo({
214214
command: "btrfs",
215215
args: [
216216
"send",
217217
"--compressed-data",
218-
join(this.snapshot.path(), send),
219-
...(last ? ["-p", this.snapshot.path(parent)] : []),
218+
join(this.snapshots.path(), send),
219+
...(last ? ["-p", this.snapshots.path(parent)] : []),
220220
"-f",
221221
join(this.filesystem.streams, this.name, send),
222222
],
223223
});
224224
if (parent) {
225-
await this.snapshot.delete(parent);
225+
await this.snapshots.delete(parent);
226226
}
227227
};
228228

src/packages/file-server/btrfs/test/filesystem.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ describe("operations with subvolumes", () => {
3030
const vol = await fs.subvolume("cocalc");
3131
expect(vol.name).toBe("cocalc");
3232
// it has no snapshots
33-
expect(await vol.snapshot.ls()).toEqual([]);
33+
expect(await vol.snapshots.ls()).toEqual([]);
3434
});
3535

3636
it("our subvolume is in the list", async () => {

src/packages/file-server/btrfs/test/subvolume-stress.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,23 @@ describe(`stress test creating ${numSnapshots} snapshots`, () => {
2222
const start = Date.now();
2323
for (let i = 0; i < numSnapshots; i++) {
2424
await writeFile(join(vol.path, `${i}.txt`), "world");
25-
await vol.snapshot.create(`snap${i}`);
25+
await vol.snapshots.create(`snap${i}`);
2626
snaps.push(`snap${i}`);
2727
}
2828
log(
2929
`created ${Math.round((numSnapshots / (Date.now() - start)) * 1000)} snapshots per second in serial`,
3030
);
3131
snaps.sort();
32-
expect((await vol.snapshot.ls()).map(({ name }) => name).sort()).toEqual(
32+
expect((await vol.snapshots.ls()).map(({ name }) => name).sort()).toEqual(
3333
snaps.sort(),
3434
);
3535
});
3636

3737
it(`delete our ${numSnapshots} snapshots`, async () => {
3838
for (let i = 0; i < numSnapshots; i++) {
39-
await vol.snapshot.delete(`snap${i}`);
39+
await vol.snapshots.delete(`snap${i}`);
4040
}
41-
expect(await vol.snapshot.ls()).toEqual([]);
41+
expect(await vol.snapshots.ls()).toEqual([]);
4242
});
4343
});
4444

src/packages/file-server/btrfs/test/subvolume.test.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ describe("the filesystem operations", () => {
8686

8787
let origStat;
8888
it("snapshot filesystem and see file is in snapshot", async () => {
89-
await vol.snapshot.create("snap");
90-
const s = await vol.fs.ls(vol.snapshot.path("snap"));
89+
await vol.snapshots.create("snap");
90+
const s = await vol.fs.ls(vol.snapshots.path("snap"));
9191
expect(s).toEqual([{ name: "a.txt", mtime: s[0].mtime, size: 5 }]);
9292

9393
const stat = await vol.fs.stat("a.txt");
@@ -101,11 +101,11 @@ describe("the filesystem operations", () => {
101101
});
102102

103103
it("snapshot still exists", async () => {
104-
expect(await vol.fs.exists(vol.snapshot.path("snap", "a.txt")));
104+
expect(await vol.fs.exists(vol.snapshots.path("snap", "a.txt")));
105105
});
106106

107107
it("copy file from snapshot and note it has the same mode as before (so much nicer than what happens with zfs)", async () => {
108-
await vol.fs.copyFile(vol.snapshot.path("snap", "a.txt"), "a.txt");
108+
await vol.fs.copyFile(vol.snapshots.path("snap", "a.txt"), "a.txt");
109109
const stat = await vol.fs.stat("a.txt");
110110
expect(stat.mode).toEqual(origStat.mode);
111111
});
@@ -179,50 +179,50 @@ describe("test snapshots", () => {
179179

180180
it("creates a volume and write a file to it", async () => {
181181
vol = await fs.subvolume("snapper");
182-
expect(await vol.snapshot.hasUnsavedChanges()).toBe(false);
182+
expect(await vol.snapshots.hasUnsavedChanges()).toBe(false);
183183
await vol.fs.writeFile("a.txt", "hello");
184-
expect(await vol.snapshot.hasUnsavedChanges()).toBe(true);
184+
expect(await vol.snapshots.hasUnsavedChanges()).toBe(true);
185185
});
186186

187187
it("snapshot the volume", async () => {
188-
expect(await vol.snapshot.ls()).toEqual([]);
189-
await vol.snapshot.create("snap1");
190-
expect((await vol.snapshot.ls()).map((x) => x.name)).toEqual(["snap1"]);
191-
expect(await vol.snapshot.hasUnsavedChanges()).toBe(false);
188+
expect(await vol.snapshots.ls()).toEqual([]);
189+
await vol.snapshots.create("snap1");
190+
expect((await vol.snapshots.ls()).map((x) => x.name)).toEqual(["snap1"]);
191+
expect(await vol.snapshots.hasUnsavedChanges()).toBe(false);
192192
});
193193

194194
it("create a file see that we know there are unsaved changes", async () => {
195195
await vol.fs.writeFile("b.txt", "world");
196196
await sudo({ command: "sync" });
197-
expect(await vol.snapshot.hasUnsavedChanges()).toBe(true);
197+
expect(await vol.snapshots.hasUnsavedChanges()).toBe(true);
198198
});
199199

200200
it("delete our file, but then read it in a snapshot", async () => {
201201
await vol.fs.unlink("a.txt");
202202
const b = await vol.fs.readFile(
203-
vol.snapshot.path("snap1", "a.txt"),
203+
vol.snapshots.path("snap1", "a.txt"),
204204
"utf8",
205205
);
206206
expect(b).toEqual("hello");
207207
});
208208

209209
it("verifies snapshot exists", async () => {
210-
expect(await vol.snapshot.exists("snap1")).toBe(true);
211-
expect(await vol.snapshot.exists("snap2")).toBe(false);
210+
expect(await vol.snapshots.exists("snap1")).toBe(true);
211+
expect(await vol.snapshots.exists("snap2")).toBe(false);
212212
});
213213

214214
it("lock our snapshot and confirm it prevents deletion", async () => {
215-
await vol.snapshot.lock("snap1");
215+
await vol.snapshots.lock("snap1");
216216
expect(async () => {
217-
await vol.snapshot.delete("snap1");
217+
await vol.snapshots.delete("snap1");
218218
}).rejects.toThrow("locked");
219219
});
220220

221221
it("unlock our snapshot and delete it", async () => {
222-
await vol.snapshot.unlock("snap1");
223-
await vol.snapshot.delete("snap1");
224-
expect(await vol.snapshot.exists("snap1")).toBe(false);
225-
expect(await vol.snapshot.ls()).toEqual([]);
222+
await vol.snapshots.unlock("snap1");
223+
await vol.snapshots.delete("snap1");
224+
expect(await vol.snapshots.exists("snap1")).toBe(false);
225+
expect(await vol.snapshots.ls()).toEqual([]);
226226
});
227227
});
228228

@@ -286,9 +286,9 @@ describe.only("test bup backups", () => {
286286
});
287287

288288
it("most recent snapshot has a backup before the restore", async () => {
289-
const s = await vol.snapshot.ls();
289+
const s = await vol.snapshots.ls();
290290
const recent = s.slice(-1)[0].name;
291-
const p = vol.snapshot.path(recent, "mydir", "file.txt");
291+
const p = vol.snapshots.path(recent, "mydir", "file.txt");
292292
expect(await vol.fs.readFile(p, "utf8")).toEqual("changed");
293293
});
294294
});

0 commit comments

Comments
 (0)