Skip to content

Commit 6ea9be4

Browse files
authored
SKStore cleanups, last week of April (#885)
2 parents 6ca32d9 + ff87985 commit 6ea9be4

File tree

19 files changed

+377
-463
lines changed

19 files changed

+377
-463
lines changed

skiplang/prelude/src/skstore/Context.sk

Lines changed: 66 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,6 @@ base class Postponable {
1515
fun perform(context: mutable Context): void;
1616
}
1717

18-
class ToWrite(
19-
dirName: DirName,
20-
key: Key,
21-
values: readonly Context ~> Array<File>,
22-
) extends Postponable {
23-
//
24-
fun perform(context: mutable Context): void {
25-
context.unsafeMaybeGetEagerDir(this.dirName) match {
26-
| Some(dir) -> dir.writeArray(context, this.key, this.values(context))
27-
| _ -> void
28-
}
29-
}
30-
}
31-
3218
/*****************************************************************************/
3319
/* Sessions. */
3420
/*****************************************************************************/
@@ -233,6 +219,13 @@ value class Tick(value: Int) uses Orderable, Show {
233219

234220
class TickFile(value: Tick) extends File uses Orderable
235221

222+
/* Time refers to the creation time of a directory.
223+
Context#time is increased using Context#timeStamp() when a directory is created.
224+
It is stored in the last element of the TimeStack of the directory.
225+
226+
Times and TimeStacks are used to order directory updates.
227+
Context#toUpdate is used as a priority queue.
228+
*/
236229
value class Time(value: Int) uses Orderable, Show {
237230
fun next(): this {
238231
!this.value = genSym(this.value + 1);
@@ -248,7 +241,9 @@ value class Time(value: Int) uses Orderable, Show {
248241
}
249242
}
250243

251-
class TimeStack private (private values: Array<Time>) uses Orderable {
244+
class TimeStack private (
245+
private values: /* Invariant: non-empty array */ Array<Time>,
246+
) uses Orderable {
252247
static fun createInput(time: Time): this {
253248
static(Array[time])
254249
}
@@ -265,25 +260,14 @@ class TimeStack private (private values: Array<Time>) uses Orderable {
265260
this
266261
}
267262

268-
fun negate(): this {
269-
!this.values = this.values.map(x -> -x);
270-
this
263+
fun getLast(): Time {
264+
this.values.last()
271265
}
272266

273-
fun maxMinus(): this {
274-
!this.values = this.values.map(x -> Time(Int::max - x.value));
267+
fun negate(): this {
268+
!this.values = this.values.map(x -> -x);
275269
this
276270
}
277-
278-
fun compare(other: TimeStack): Order {
279-
for (i in Range(0, this.values.size())) {
280-
if (i >= other.values.size()) return GT();
281-
cmp = this.values[i].compare(other.values[i]);
282-
if (cmp != EQ()) return cmp;
283-
};
284-
if (other.values.size() > this.values.size()) return LT();
285-
EQ()
286-
}
287271
}
288272

289273
/*****************************************************************************/
@@ -341,7 +325,10 @@ mutable class Context private {
341325
mutable globals: SortedMap<String, File> = SortedMap[],
342326
private mutable persistents: SortedMap<String, File> = SortedMap[],
343327
private mutable dirty: SortedMap<DirName, SortedSet<Key>> = SortedMap[],
344-
private mutable dirtyReaders: List<ArrowKey> = List[],
328+
private mutable dirtyReaders: /* parentName => childName => keys */ SortedMap<
329+
DirName,
330+
SortedMap<DirName, SortedSet<Key>>,
331+
> = SortedMap[],
345332
mutable canReuse: CanReuse = CRIfMatch(),
346333
private mutable arrowStack: List<(ArrowKey, TimeStack)> = List[],
347334
private mutable lazyGets: SortedSet<Path> = SortedSet[],
@@ -352,7 +339,7 @@ mutable class Context private {
352339
private mutable dirsWithSharedSubDirs: SortedSet<DirName> = SortedSet[],
353340
private mutable sharedSubDirsRefCount: SortedMap<DirName, Int> = SortedMap[],
354341
mutable writeChecker: ?(mutable WriteChecker) = None(),
355-
mutable purgeFrom: (mutable Context, Dir) ~> Tick = (ctx, _) ~>
342+
mutable purgeFrom: (readonly Context, Dir) ~> Tick = (ctx, _) ~>
356343
Tick(ctx.getTick().value - 1000),
357344
mutable sourceOverride: ?Path = None(),
358345
} {
@@ -559,11 +546,9 @@ mutable class Context private {
559546
this.!newDirs = this.newDirs.add(preDirName);
560547
time = this.timeStamp();
561548
preDir = EagerDir::create{
562-
time,
563549
input => false,
564550
timeStack => TimeStack::createInput(time),
565551
dirName => preDirName,
566-
totalSize => 0,
567552
creator => this.currentArrow(),
568553
};
569554
dir.unsafeIterKeys((key, _time) -> {
@@ -573,8 +558,7 @@ mutable class Context private {
573558
!preDir = preDir.writeEntry(this, source, source, key, values);
574559
});
575560
this.setDir(preDir);
576-
this.updateDirtyReaders(Path::dirTag(preDirName));
577-
this.setDir(preDir)
561+
this.updateDirtyReaders(Path::dirTag(preDirName))
578562
| Some(preDir) ->
579563
(isReset, changes) = dir.getChangesAfter(this.tick.prev());
580564
for (key in changes) {
@@ -612,7 +596,15 @@ mutable class Context private {
612596
| None() -> continue
613597
| Some(x) -> x
614598
};
615-
this.!dirtyReaders = List.Cons(reader, this.dirtyReaders);
599+
this.!dirtyReaders[reader.parentName] = {
600+
map = this.dirtyReaders.maybeGet(reader.parentName).default(
601+
SortedMap[],
602+
);
603+
map.set(
604+
reader.childName,
605+
map.maybeGet(reader.childName).default(SortedSet[]).set(reader.key),
606+
)
607+
};
616608
time = if (reader.parentName == reader.childName) {
617609
-child.getTimeStack()
618610
} else {
@@ -697,53 +689,36 @@ mutable class Context private {
697689
print_debug(`------------ UPDATE (TICK: ${this.tick}) ------------`);
698690
};
699691

700-
_ = this.timeStamp();
701-
702692
this.updateLazyGets();
703693

704-
dirtyReaders = mutable Map<DirName, mutable Map<DirName, SortedSet<Key>>>[];
705-
706694
loop {
707-
for (reader in this.dirtyReaders) {
708-
if (!dirtyReaders.containsKey(reader.parentName)) {
709-
dirtyReaders![reader.parentName] = mutable Map[];
710-
};
711-
712-
if (!dirtyReaders[reader.parentName].containsKey(reader.childName)) {
713-
dirtyReaders[reader.parentName]![reader.childName] = SortedSet[];
714-
};
715-
dirtyReaders[reader.parentName]![reader.childName] = dirtyReaders[
716-
reader.parentName,
717-
][reader.childName].set(reader.key);
718-
};
719-
this.!dirtyReaders = List[];
720-
toUpdate = this.toUpdate.minimum();
721-
toUpdate match {
695+
this.toUpdate.removeMin() match {
722696
| None() ->
723697
this.!dirty = SortedMap[];
724-
invariant(this.dirtyReaders.isEmpty());
698+
this.!dirtyReaders = SortedMap[];
725699
withPostponables = this.checkPostponables();
726700
withPre = this.updatePre();
727701
withChanges = withPostponables || withPre;
728702
this.!tick = this.tick.next();
729703
break withChanges
730-
| Some((time, Arrow(parentName, childName))) ->
731-
this.!toUpdate = this.toUpdate.remove(time);
704+
| Some((_time, Arrow(parentName, childName), toUpdate)) ->
705+
this.!toUpdate = toUpdate;
732706
this.unsafeMaybeGetDir(childName) match {
733707
| None()
734708
| Some(DeletedDir _) ->
735709
void
736-
| Some(child @ LazyDir _) ->
737-
child.update(this, dirtyReaders.maybeGet(child.dirName))
710+
| Some(dir @ LazyDir _) ->
711+
invariant(parentName == childName);
712+
dir.update(this, this.dirtyReaders.maybeGet(dir.dirName))
738713
| Some(child @ EagerDir _) ->
739714
parentMaps = child.parents.maybeGet(parentName) match {
740715
| None() -> invariant_violation("Could not find parent")
741716
| Some(f) -> f
742717
};
743718
EagerDir::update(
744719
this,
745-
this.dirty,
746-
dirtyReaders,
720+
this.dirty.maybeGet(parentName),
721+
this.dirtyReaders.maybeGet(parentName),
747722
parentName,
748723
parentMaps,
749724
child,
@@ -805,8 +780,7 @@ mutable class Context private {
805780
};
806781
if (producedAnyOutput) {
807782
// then we need to produce a checkpoint for flushing and committing
808-
ourTime = this.tick.value.toString();
809-
writer.write(`:${ourTime}\n`);
783+
writer.write(`:${this.tick}\n`);
810784
writer.flush();
811785
flushStdout();
812786
};
@@ -886,6 +860,8 @@ mutable class Context private {
886860
optOnDelete: ?Postponable = None(),
887861
): EHandle<K, V> {
888862
this.mkdirMulti(
863+
convKey,
864+
convValue,
889865
dirName,
890866
content.map(kv -> {
891867
(key, value) = kv;
@@ -894,17 +870,18 @@ mutable class Context private {
894870
ignoreIfExists,
895871
optOnCreate,
896872
optOnDelete,
897-
);
898-
EHandle(convKey, convValue, dirName)
873+
)
899874
}
900875

901-
mutable fun mkdirMulti(
876+
mutable fun mkdirMulti<K: Key, V: File>(
877+
convKey: Key ~> K,
878+
convValue: File ~> V,
902879
dirName: DirName,
903-
content: Array<(Key, Array<File>)> = Array[],
880+
content: Array<(K, Array<V>)> = Array[],
904881
ignoreIfExists: Bool = false,
905882
optOnCreate: ?Postponable = None(),
906883
optOnDelete: ?Postponable = None(),
907-
): void {
884+
): EHandle<K, V> {
908885
this.unsafeMaybeGetEagerDir(dirName) match {
909886
| Some(dir) ->
910887
if (dir.creator != this.currentArrow()) {
@@ -913,7 +890,7 @@ mutable class Context private {
913890
throw DirAlreadyExists(dirName);
914891
} else if (ignoreIfExists) {
915892
this.!newDirs = this.newDirs.add(dirName);
916-
return void
893+
return EHandle(convKey, convValue, dirName)
917894
}
918895
| _ -> void
919896
};
@@ -929,8 +906,7 @@ mutable class Context private {
929906
}
930907
});
931908

932-
vector: mutable Vector<FixedRow<Array<File>>> = mutable Vector[];
933-
time = this.timeStamp();
909+
vector: mutable Vector<FixedRow<Array<V>>> = mutable Vector[];
934910

935911
n = content.size();
936912
if (n > 0) {
@@ -954,21 +930,20 @@ mutable class Context private {
954930
};
955931
fixedData = FixedDataMap::create(vector);
956932

957-
totalSize = fixedData.data.size();
958933
creator = this.currentArrow();
934+
time = this.timeStamp();
959935
dir = EagerDir::create{
960-
time,
961936
timeStack => TimeStack::create(this, time),
962937
input => true,
963938
dirName,
964939
fixedData,
965-
totalSize,
966940
creator,
967941
optOnDelete,
968942
};
969943
this.setDir(dir);
970944
this.!newDirs = this.newDirs.add(dirName);
971-
optOnCreate.each(this.postpone)
945+
optOnCreate.each(this.postpone);
946+
EHandle(convKey, convValue, dirName)
972947
}
973948

974949
mutable fun setDir(dir: Dir): void {
@@ -981,6 +956,15 @@ mutable class Context private {
981956
this.dirs.get(dirName);
982957
}
983958

959+
mutable fun maybeGetDir<T: File>(dirName: DirName): ?Dir {
960+
this.addRead(Path::dirTag(dirName));
961+
this.dirs.maybeGet(dirName);
962+
}
963+
964+
readonly fun unsafeMaybeGetDir<T: File>(dirName: DirName): ?Dir {
965+
this.dirs.maybeGet(dirName);
966+
}
967+
984968
readonly fun unsafeGetDir(dirName: DirName): Dir {
985969
this.dirs.get(dirName);
986970
}
@@ -1045,7 +1029,7 @@ mutable class Context private {
10451029

10461030
mutable fun removeDir(dirName: DirName): void {
10471031
if (this.debugMode) {
1048-
print_debug("REMOVED: " + dirName);
1032+
print_debug(`REMOVED: ${dirName}`);
10491033
};
10501034
this.unsafeMaybeGetEagerDir(dirName) match {
10511035
| None() -> void
@@ -1082,15 +1066,6 @@ mutable class Context private {
10821066
}
10831067
}
10841068

1085-
mutable fun maybeGetDir<T: File>(dirName: DirName): ?Dir {
1086-
this.addRead(Path::dirTag(dirName));
1087-
this.dirs.maybeGet(dirName);
1088-
}
1089-
1090-
readonly fun unsafeMaybeGetDir<T: File>(dirName: DirName): ?Dir {
1091-
this.dirs.maybeGet(dirName);
1092-
}
1093-
10941069
mutable fun addRead(path: Path): void {
10951070
this.!reads = this.reads.set(path);
10961071
}
@@ -1157,7 +1132,7 @@ private class Dirs{private state: DMap<DirName, Dir> = DMap::empty()} {
11571132
this.maybeGet(key) match {
11581133
| None() ->
11591134
// printBacktrace();
1160-
invariant_violation("Directory not found: " + key)
1135+
invariant_violation(`Directory not found: ${key}`)
11611136
| Some(x) -> x
11621137
}
11631138
}
@@ -1205,15 +1180,11 @@ fun import(
12051180
targetCtx.setDir(dir);
12061181
}
12071182
| Some(inputDir) ->
1208-
!inputDir = inputDir.writeArraySourceManyReturnDir(
1183+
inputDir.writeArraySourceMany(
12091184
targetCtx,
12101185
entries.iterator(),
1211-
);
1212-
if (isReset) {
1213-
writerPath = Path::gen(dir.dirName);
1214-
!inputDir = inputDir.reset(targetCtx, writerPath, changedKeys);
1215-
};
1216-
targetCtx.setDir(inputDir)
1186+
if (isReset) Some((dir.dirName, changedKeys)) else None(),
1187+
)
12171188
}
12181189
| Some(_) -> invariant_violation("Error import: incompatible dir types")
12191190
}

skiplang/prelude/src/skstore/DeletedDir.sk

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ module SKStore;
55

66
class DeletedDir protected {} extends Dir {
77
static fun ofDir(dir: Dir): this {
8-
time = dir.getTime();
98
timeStack = dir.getTimeStack();
109
dirName = dir.getDirName();
11-
static{time, timeStack, dirName}
10+
static{timeStack, dirName}
1211
}
1312

1413
fun getArrayRaw(Key): Array<File> {

skiplang/prelude/src/skstore/Dir.sk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
module SKStore;
66

7-
base class Dir protected {time: Time, timeStack: TimeStack, dirName: DirName} {
7+
base class Dir protected {timeStack: TimeStack, dirName: DirName} {
88
/**
99
* Returns an array of files associated with a key.
1010
* The array is empty if the key does not exist.
@@ -39,7 +39,7 @@ base class Dir protected {time: Time, timeStack: TimeStack, dirName: DirName} {
3939
* Returns the creation time of that directory.
4040
*/
4141
fun getTime(): Time {
42-
this.time
42+
this.timeStack.getLast()
4343
}
4444

4545
/**

0 commit comments

Comments
 (0)