@fluidframework/merge-tree 0.59.2000-63294 → 0.59.3000-66610
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/.eslintrc.js +0 -1
- package/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +39 -33
- package/dist/client.js.map +1 -1
- package/dist/collections.d.ts.map +1 -1
- package/dist/collections.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/localReference.d.ts +58 -2
- package/dist/localReference.d.ts.map +1 -1
- package/dist/localReference.js +60 -35
- package/dist/localReference.js.map +1 -1
- package/dist/mergeTree.d.ts +25 -21
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +72 -79
- package/dist/mergeTree.js.map +1 -1
- package/dist/partialLengths.js +10 -10
- package/dist/partialLengths.js.map +1 -1
- package/dist/referencePositions.d.ts +54 -0
- package/dist/referencePositions.d.ts.map +1 -0
- package/dist/referencePositions.js +90 -0
- package/dist/referencePositions.js.map +1 -0
- package/dist/segmentGroupCollection.js +1 -1
- package/dist/segmentGroupCollection.js.map +1 -1
- package/dist/segmentPropertiesManager.js +5 -5
- package/dist/segmentPropertiesManager.js.map +1 -1
- package/dist/snapshotChunks.js.map +1 -1
- package/dist/snapshotLoader.d.ts.map +1 -1
- package/dist/snapshotLoader.js +9 -9
- package/dist/snapshotLoader.js.map +1 -1
- package/dist/snapshotV1.js +7 -7
- package/dist/snapshotV1.js.map +1 -1
- package/dist/snapshotlegacy.js +5 -5
- package/dist/snapshotlegacy.js.map +1 -1
- package/dist/sortedSegmentSet.d.ts.map +1 -1
- package/dist/sortedSegmentSet.js.map +1 -1
- package/lib/client.d.ts +4 -2
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +10 -4
- package/lib/client.js.map +1 -1
- package/lib/collections.d.ts.map +1 -1
- package/lib/collections.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/localReference.d.ts +58 -2
- package/lib/localReference.d.ts.map +1 -1
- package/lib/localReference.js +54 -29
- package/lib/localReference.js.map +1 -1
- package/lib/mergeTree.d.ts +25 -21
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +39 -42
- package/lib/mergeTree.js.map +1 -1
- package/lib/referencePositions.d.ts +54 -0
- package/lib/referencePositions.d.ts.map +1 -0
- package/lib/referencePositions.js +78 -0
- package/lib/referencePositions.js.map +1 -0
- package/lib/segmentPropertiesManager.js.map +1 -1
- package/lib/snapshotChunks.js.map +1 -1
- package/lib/snapshotLoader.d.ts.map +1 -1
- package/lib/snapshotLoader.js.map +1 -1
- package/lib/snapshotV1.js.map +1 -1
- package/lib/snapshotlegacy.js.map +1 -1
- package/lib/sortedSegmentSet.d.ts.map +1 -1
- package/lib/sortedSegmentSet.js.map +1 -1
- package/package.json +83 -14
- package/src/client.ts +19 -17
- package/src/collections.ts +26 -52
- package/src/index.ts +1 -0
- package/src/localReference.ts +69 -36
- package/src/mergeTree.ts +71 -90
- package/src/referencePositions.ts +122 -0
- package/src/snapshotChunks.ts +8 -8
- package/src/snapshotLoader.ts +4 -4
- package/src/snapshotV1.ts +1 -1
- package/src/snapshotlegacy.ts +1 -1
- package/src/sortedSegmentSet.ts +3 -3
package/src/mergeTree.ts
CHANGED
|
@@ -50,27 +50,19 @@ import {
|
|
|
50
50
|
matchProperties,
|
|
51
51
|
PropertySet,
|
|
52
52
|
} from "./properties";
|
|
53
|
+
import {
|
|
54
|
+
RangeStackMap,
|
|
55
|
+
ReferencePosition,
|
|
56
|
+
refGetRangeLabels,
|
|
57
|
+
refGetTileLabels,
|
|
58
|
+
refHasRangeLabel,
|
|
59
|
+
refHasRangeLabels,
|
|
60
|
+
refHasTileLabel,
|
|
61
|
+
refHasTileLabels,
|
|
62
|
+
} from "./referencePositions";
|
|
53
63
|
import { SegmentGroupCollection } from "./segmentGroupCollection";
|
|
54
64
|
import { PropertiesManager } from "./segmentPropertiesManager";
|
|
55
65
|
|
|
56
|
-
export interface ReferencePosition {
|
|
57
|
-
properties?: PropertySet;
|
|
58
|
-
refType: ReferenceType;
|
|
59
|
-
// True if this reference is a segment.
|
|
60
|
-
isLeaf(): boolean;
|
|
61
|
-
getSegment(): ISegment | undefined;
|
|
62
|
-
getOffset(): number;
|
|
63
|
-
addProperties(newProps: PropertySet, op?: ICombiningOp): void;
|
|
64
|
-
hasTileLabels(): boolean;
|
|
65
|
-
hasRangeLabels(): boolean;
|
|
66
|
-
hasTileLabel(label: string): boolean;
|
|
67
|
-
hasRangeLabel(label: string): boolean;
|
|
68
|
-
getTileLabels(): string[] | undefined;
|
|
69
|
-
getRangeLabels(): string[] | undefined;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export type RangeStackMap = MapLike<Stack<ReferencePosition>>;
|
|
73
|
-
|
|
74
66
|
export interface IMergeNodeCommon {
|
|
75
67
|
parent?: IMergeBlock;
|
|
76
68
|
/**
|
|
@@ -265,7 +257,7 @@ export class MergeNode implements IMergeNodeCommon {
|
|
|
265
257
|
}
|
|
266
258
|
|
|
267
259
|
function addTile(tile: ReferencePosition, tiles: object) {
|
|
268
|
-
const tileLabels = tile
|
|
260
|
+
const tileLabels = refGetTileLabels(tile);
|
|
269
261
|
if (tileLabels) {
|
|
270
262
|
for (const tileLabel of tileLabels) {
|
|
271
263
|
tiles[tileLabel] = tile;
|
|
@@ -274,7 +266,7 @@ function addTile(tile: ReferencePosition, tiles: object) {
|
|
|
274
266
|
}
|
|
275
267
|
|
|
276
268
|
function addTileIfNotPresent(tile: ReferencePosition, tiles: object) {
|
|
277
|
-
const tileLabels = tile
|
|
269
|
+
const tileLabels = refGetTileLabels(tile);
|
|
278
270
|
if (tileLabels) {
|
|
279
271
|
for (const tileLabel of tileLabels) {
|
|
280
272
|
if (tiles[tileLabel] === undefined) {
|
|
@@ -345,9 +337,9 @@ function addNodeReferences(
|
|
|
345
337
|
addTileIfNotPresent(segment, leftmostTiles);
|
|
346
338
|
}
|
|
347
339
|
if (segment.refType & (ReferenceType.NestBegin | ReferenceType.NestEnd)) {
|
|
348
|
-
const rangeLabels = segment
|
|
340
|
+
const rangeLabels = refGetRangeLabels(segment);
|
|
349
341
|
if (rangeLabels) {
|
|
350
|
-
for (const label of
|
|
342
|
+
for (const label of rangeLabels) {
|
|
351
343
|
updateRangeInfo(label, segment);
|
|
352
344
|
}
|
|
353
345
|
}
|
|
@@ -362,7 +354,7 @@ function addNodeReferences(
|
|
|
362
354
|
addTileIfNotPresent(lref, leftmostTiles);
|
|
363
355
|
}
|
|
364
356
|
if (lref.refType & (ReferenceType.NestBegin | ReferenceType.NestEnd)) {
|
|
365
|
-
for (const label of lref
|
|
357
|
+
for (const label of refGetRangeLabels(lref)!) {
|
|
366
358
|
updateRangeInfo(label, lref);
|
|
367
359
|
}
|
|
368
360
|
}
|
|
@@ -622,43 +614,9 @@ export abstract class BaseSegment extends MergeNode implements ISegment {
|
|
|
622
614
|
protected abstract createSplitSegmentAt(pos: number): BaseSegment | undefined;
|
|
623
615
|
}
|
|
624
616
|
|
|
625
|
-
export const reservedTileLabelsKey = "referenceTileLabels";
|
|
626
|
-
export const reservedRangeLabelsKey = "referenceRangeLabels";
|
|
627
617
|
export const reservedMarkerIdKey = "markerId";
|
|
628
618
|
export const reservedMarkerSimpleTypeKey = "markerSimpleType";
|
|
629
619
|
|
|
630
|
-
export const refGetTileLabels = (refPos: ReferencePosition) =>
|
|
631
|
-
(refPos.refType & ReferenceType.Tile)
|
|
632
|
-
&& refPos.properties ? refPos.properties[reservedTileLabelsKey] as string[] : undefined;
|
|
633
|
-
|
|
634
|
-
export const refGetRangeLabels = (refPos: ReferencePosition) =>
|
|
635
|
-
(refPos.refType & (ReferenceType.NestBegin | ReferenceType.NestEnd))
|
|
636
|
-
&& refPos.properties ? refPos.properties[reservedRangeLabelsKey] as string[] : undefined;
|
|
637
|
-
|
|
638
|
-
export function refHasTileLabel(refPos: ReferencePosition, label: string) {
|
|
639
|
-
const tileLabels = refPos.getTileLabels();
|
|
640
|
-
if (tileLabels) {
|
|
641
|
-
for (const refLabel of tileLabels) {
|
|
642
|
-
if (label === refLabel) {
|
|
643
|
-
return true;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
return false;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
export function refHasRangeLabel(refPos: ReferencePosition, label: string) {
|
|
651
|
-
const rangeLabels = refPos.getRangeLabels();
|
|
652
|
-
if (rangeLabels) {
|
|
653
|
-
for (const refLabel of rangeLabels) {
|
|
654
|
-
if (label === refLabel) {
|
|
655
|
-
return true;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
return false;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
620
|
export interface IJSONMarkerSegment extends IJSONSegment {
|
|
663
621
|
marker: IMarkerDef;
|
|
664
622
|
}
|
|
@@ -728,26 +686,39 @@ export class Marker extends BaseSegment implements ReferencePosition {
|
|
|
728
686
|
}
|
|
729
687
|
}
|
|
730
688
|
|
|
689
|
+
/**
|
|
690
|
+
* @deprecated - use refHasTileLabels
|
|
691
|
+
*/
|
|
731
692
|
hasTileLabels() {
|
|
732
|
-
return
|
|
693
|
+
return refHasTileLabels(this);
|
|
733
694
|
}
|
|
734
|
-
|
|
695
|
+
/**
|
|
696
|
+
* @deprecated - use refHasRangeLabels
|
|
697
|
+
*/
|
|
735
698
|
hasRangeLabels() {
|
|
736
|
-
return
|
|
699
|
+
return refHasRangeLabels(this);
|
|
737
700
|
}
|
|
738
|
-
|
|
701
|
+
/**
|
|
702
|
+
* @deprecated - use refHasTileLabel
|
|
703
|
+
*/
|
|
739
704
|
hasTileLabel(label: string): boolean {
|
|
740
705
|
return refHasTileLabel(this, label);
|
|
741
706
|
}
|
|
742
|
-
|
|
707
|
+
/**
|
|
708
|
+
* @deprecated - use refHasRangeLabel
|
|
709
|
+
*/
|
|
743
710
|
hasRangeLabel(label: string): boolean {
|
|
744
711
|
return refHasRangeLabel(this, label);
|
|
745
712
|
}
|
|
746
|
-
|
|
713
|
+
/**
|
|
714
|
+
* @deprecated - use refGetTileLabels
|
|
715
|
+
*/
|
|
747
716
|
getTileLabels(): string[] | undefined {
|
|
748
717
|
return refGetTileLabels(this);
|
|
749
718
|
}
|
|
750
|
-
|
|
719
|
+
/**
|
|
720
|
+
* @deprecated - use refGetRangeLabels
|
|
721
|
+
*/
|
|
751
722
|
getRangeLabels(): string[] | undefined {
|
|
752
723
|
return refGetRangeLabels(this);
|
|
753
724
|
}
|
|
@@ -774,7 +745,7 @@ export class Marker extends BaseSegment implements ReferencePosition {
|
|
|
774
745
|
if (id) {
|
|
775
746
|
bbuf += ` (${id}) `;
|
|
776
747
|
}
|
|
777
|
-
const tileLabels = this
|
|
748
|
+
const tileLabels = refGetTileLabels(this);
|
|
778
749
|
if (tileLabels) {
|
|
779
750
|
lbuf += "tile -- ";
|
|
780
751
|
for (let i = 0, len = tileLabels.length; i < len; i++) {
|
|
@@ -785,7 +756,7 @@ export class Marker extends BaseSegment implements ReferencePosition {
|
|
|
785
756
|
lbuf += tileLabel;
|
|
786
757
|
}
|
|
787
758
|
}
|
|
788
|
-
const rangeLabels = this
|
|
759
|
+
const rangeLabels = refGetRangeLabels(this);
|
|
789
760
|
if (rangeLabels) {
|
|
790
761
|
let rangeKind = "begin";
|
|
791
762
|
if (this.refType & ReferenceType.NestEnd) {
|
|
@@ -931,7 +902,7 @@ interface IMarkerSearchRangeInfo {
|
|
|
931
902
|
|
|
932
903
|
function applyLeafRangeMarker(marker: Marker, searchInfo: IMarkerSearchRangeInfo) {
|
|
933
904
|
for (const rangeLabel of searchInfo.rangeLabels) {
|
|
934
|
-
if (marker
|
|
905
|
+
if (refHasRangeLabel(marker, rangeLabel)) {
|
|
935
906
|
let currentStack = searchInfo.stacks[rangeLabel];
|
|
936
907
|
if (currentStack === undefined) {
|
|
937
908
|
currentStack = new Stack<Marker>();
|
|
@@ -981,7 +952,7 @@ function recordTileStart(
|
|
|
981
952
|
end: number,
|
|
982
953
|
searchInfo: IReferenceSearchInfo) {
|
|
983
954
|
if (Marker.is(segment)) {
|
|
984
|
-
if (segment
|
|
955
|
+
if (refHasTileLabel(segment, searchInfo.tileLabel)) {
|
|
985
956
|
searchInfo.tile = segment;
|
|
986
957
|
}
|
|
987
958
|
}
|
|
@@ -994,7 +965,7 @@ function tileShift(
|
|
|
994
965
|
if (node.isLeaf()) {
|
|
995
966
|
const seg = node;
|
|
996
967
|
if ((searchInfo.mergeTree.localNetLength(seg) > 0) && Marker.is(seg)) {
|
|
997
|
-
if (seg
|
|
968
|
+
if (refHasTileLabel(seg, searchInfo.tileLabel)) {
|
|
998
969
|
searchInfo.tile = seg;
|
|
999
970
|
}
|
|
1000
971
|
}
|
|
@@ -1134,7 +1105,7 @@ export class MergeTree {
|
|
|
1134
1105
|
// and update the block's info.
|
|
1135
1106
|
for (let childIndex = 0;
|
|
1136
1107
|
childIndex < maxChildren && nodeIndex < nodes.length; // While we still have children & nodes left
|
|
1137
|
-
childIndex
|
|
1108
|
+
childIndex++, nodeIndex++ // Advance to next child & node
|
|
1138
1109
|
) {
|
|
1139
1110
|
// Insert the next node into the current block
|
|
1140
1111
|
this.addNode(block, nodes[nodeIndex]);
|
|
@@ -1202,11 +1173,13 @@ export class MergeTree {
|
|
|
1202
1173
|
} else {
|
|
1203
1174
|
// Notify maintenance event observers that the segment is being unlinked from the MergeTree
|
|
1204
1175
|
if (this.mergeTreeMaintenanceCallback) {
|
|
1205
|
-
this.mergeTreeMaintenanceCallback(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1176
|
+
this.mergeTreeMaintenanceCallback(
|
|
1177
|
+
{
|
|
1178
|
+
operation: MergeTreeMaintenanceType.UNLINK,
|
|
1179
|
+
deltaSegments: [{ segment }],
|
|
1180
|
+
},
|
|
1181
|
+
undefined,
|
|
1182
|
+
);
|
|
1210
1183
|
}
|
|
1211
1184
|
|
|
1212
1185
|
segment.parent = undefined;
|
|
@@ -1223,11 +1196,13 @@ export class MergeTree {
|
|
|
1223
1196
|
if (canAppend) {
|
|
1224
1197
|
prevSegment!.append(segment);
|
|
1225
1198
|
if (this.mergeTreeMaintenanceCallback) {
|
|
1226
|
-
this.mergeTreeMaintenanceCallback(
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1199
|
+
this.mergeTreeMaintenanceCallback(
|
|
1200
|
+
{
|
|
1201
|
+
operation: MergeTreeMaintenanceType.APPEND,
|
|
1202
|
+
deltaSegments: [{ segment: prevSegment! }, { segment }],
|
|
1203
|
+
},
|
|
1204
|
+
undefined,
|
|
1205
|
+
);
|
|
1231
1206
|
}
|
|
1232
1207
|
segment.parent = undefined;
|
|
1233
1208
|
segment.trackingCollection.trackingGroups.forEach((tg) => tg.unlink(segment));
|
|
@@ -1461,7 +1436,7 @@ export class MergeTree {
|
|
|
1461
1436
|
const segment = node;
|
|
1462
1437
|
const removalInfo = toRemovalInfo(segment);
|
|
1463
1438
|
|
|
1464
|
-
if(removalInfo !== undefined
|
|
1439
|
+
if (removalInfo !== undefined
|
|
1465
1440
|
&& removalInfo.removedSeq !== UnassignedSequenceNumber
|
|
1466
1441
|
&& removalInfo.removedSeq <= refSeq) {
|
|
1467
1442
|
// this segment is a tombstone eligible for zamboni
|
|
@@ -1485,7 +1460,7 @@ export class MergeTree {
|
|
|
1485
1460
|
// the segment was inserted and removed before the
|
|
1486
1461
|
// this context, so it will never exist for this
|
|
1487
1462
|
// context
|
|
1488
|
-
if(removalInfo !== undefined
|
|
1463
|
+
if (removalInfo !== undefined
|
|
1489
1464
|
&& removalInfo.removedSeq !== UnassignedSequenceNumber) {
|
|
1490
1465
|
return undefined;
|
|
1491
1466
|
}
|
|
@@ -1707,10 +1682,10 @@ export class MergeTree {
|
|
|
1707
1682
|
nodesToUpdate.push(pendingSegment.parent!);
|
|
1708
1683
|
}
|
|
1709
1684
|
deltaSegments.push({
|
|
1710
|
-
segment:pendingSegment,
|
|
1685
|
+
segment: pendingSegment,
|
|
1711
1686
|
});
|
|
1712
1687
|
});
|
|
1713
|
-
if(this.mergeTreeMaintenanceCallback) {
|
|
1688
|
+
if (this.mergeTreeMaintenanceCallback) {
|
|
1714
1689
|
this.mergeTreeMaintenanceCallback(
|
|
1715
1690
|
{
|
|
1716
1691
|
deltaSegments,
|
|
@@ -1874,7 +1849,7 @@ export class MergeTree {
|
|
|
1874
1849
|
}
|
|
1875
1850
|
const backLen = this.nodeLength(backSeg, this.collabWindow.currentSeq, clientId);
|
|
1876
1851
|
// ignore removed segments
|
|
1877
|
-
if(backLen === undefined) {
|
|
1852
|
+
if (backLen === undefined) {
|
|
1878
1853
|
return true;
|
|
1879
1854
|
}
|
|
1880
1855
|
// Find the nearest 0 length seg we can insert over, as all other inserts
|
|
@@ -1940,7 +1915,7 @@ export class MergeTree {
|
|
|
1940
1915
|
remoteClientPosition: number,
|
|
1941
1916
|
remoteClientRefSeq: number,
|
|
1942
1917
|
remoteClientId: number): number | undefined {
|
|
1943
|
-
if(remoteClientRefSeq < this.collabWindow.minSeq) {
|
|
1918
|
+
if (remoteClientRefSeq < this.collabWindow.minSeq) {
|
|
1944
1919
|
return undefined;
|
|
1945
1920
|
}
|
|
1946
1921
|
|
|
@@ -2001,9 +1976,9 @@ export class MergeTree {
|
|
|
2001
1976
|
const saveIfLocal = (locSegment: ISegment) => {
|
|
2002
1977
|
// Save segment so can assign sequence number when acked by server
|
|
2003
1978
|
if (this.collabWindow.collaborating) {
|
|
2004
|
-
if ((locSegment.seq === UnassignedSequenceNumber) &&
|
|
2005
|
-
(clientId === this.collabWindow.clientId)) {
|
|
1979
|
+
if ((locSegment.seq === UnassignedSequenceNumber) && (clientId === this.collabWindow.clientId)) {
|
|
2006
1980
|
segmentGroup = this.addToPendingList(locSegment, segmentGroup, localSeq);
|
|
1981
|
+
// eslint-disable-next-line @typescript-eslint/brace-style
|
|
2007
1982
|
}
|
|
2008
1983
|
// LocSegment.seq === 0 when coming from SharedSegmentSequence.loadBody()
|
|
2009
1984
|
// In all other cases this has to be true (checked by addToLRUSet):
|
|
@@ -2070,7 +2045,7 @@ export class MergeTree {
|
|
|
2070
2045
|
operation: MergeTreeMaintenanceType.SPLIT,
|
|
2071
2046
|
deltaSegments: [{ segment }, { segment: next }],
|
|
2072
2047
|
},
|
|
2073
|
-
|
|
2048
|
+
undefined);
|
|
2074
2049
|
}
|
|
2075
2050
|
|
|
2076
2051
|
return { next };
|
|
@@ -2178,7 +2153,7 @@ export class MergeTree {
|
|
|
2178
2153
|
for (childIndex = 0; childIndex < block.childCount; childIndex++) {
|
|
2179
2154
|
child = children[childIndex];
|
|
2180
2155
|
const len = this.nodeLength(child, refSeq, clientId);
|
|
2181
|
-
if(len === undefined) {
|
|
2156
|
+
if (len === undefined) {
|
|
2182
2157
|
// if the seg len in undefined, the segment
|
|
2183
2158
|
// will be removed, so should just be skipped for now
|
|
2184
2159
|
continue;
|
|
@@ -2467,6 +2442,9 @@ export class MergeTree {
|
|
|
2467
2442
|
}
|
|
2468
2443
|
}
|
|
2469
2444
|
|
|
2445
|
+
/**
|
|
2446
|
+
* @deprecated - use removeLocalReferencePosition
|
|
2447
|
+
*/
|
|
2470
2448
|
public removeLocalReference(segment: ISegment, lref: LocalReference) {
|
|
2471
2449
|
if (segment.localRefs) {
|
|
2472
2450
|
const removedRef = segment.localRefs.removeLocalRef(lref);
|
|
@@ -2477,6 +2455,9 @@ export class MergeTree {
|
|
|
2477
2455
|
}
|
|
2478
2456
|
}
|
|
2479
2457
|
|
|
2458
|
+
/**
|
|
2459
|
+
* @deprecated - use createLocalReference
|
|
2460
|
+
*/
|
|
2480
2461
|
public addLocalReference(lref: LocalReference) {
|
|
2481
2462
|
const segment = lref.segment!;
|
|
2482
2463
|
let localRefs = segment.localRefs;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Stack } from "./collections";
|
|
7
|
+
import { ISegment } from "./mergeTree";
|
|
8
|
+
import { ReferenceType, ICombiningOp } from "./ops";
|
|
9
|
+
import { PropertySet, MapLike } from "./properties";
|
|
10
|
+
|
|
11
|
+
export const reservedTileLabelsKey = "referenceTileLabels";
|
|
12
|
+
export const reservedRangeLabelsKey = "referenceRangeLabels";
|
|
13
|
+
|
|
14
|
+
export const refGetTileLabels = (refPos: ReferencePosition): string[] | undefined =>
|
|
15
|
+
// eslint-disable-next-line no-bitwise
|
|
16
|
+
(refPos.refType & ReferenceType.Tile)
|
|
17
|
+
&& refPos.properties ? refPos.properties[reservedTileLabelsKey] as string[] : undefined;
|
|
18
|
+
|
|
19
|
+
export const refGetRangeLabels = (refPos: ReferencePosition): string[] | undefined =>
|
|
20
|
+
// eslint-disable-next-line no-bitwise
|
|
21
|
+
(refPos.refType & (ReferenceType.NestBegin | ReferenceType.NestEnd))
|
|
22
|
+
&& refPos.properties ? refPos.properties[reservedRangeLabelsKey] as string[] : undefined;
|
|
23
|
+
|
|
24
|
+
export function refHasTileLabel(refPos: ReferencePosition, label: string): boolean {
|
|
25
|
+
const tileLabels = refGetTileLabels(refPos);
|
|
26
|
+
if (tileLabels) {
|
|
27
|
+
for (const refLabel of tileLabels) {
|
|
28
|
+
if (label === refLabel) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function refHasRangeLabel(refPos: ReferencePosition, label: string): boolean {
|
|
37
|
+
const rangeLabels = refGetRangeLabels(refPos);
|
|
38
|
+
if (rangeLabels) {
|
|
39
|
+
for (const refLabel of rangeLabels) {
|
|
40
|
+
if (label === refLabel) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
export function refHasTileLabels(refPos: ReferencePosition): boolean {
|
|
48
|
+
return refGetTileLabels(refPos) !== undefined;
|
|
49
|
+
}
|
|
50
|
+
export function refHasRangeLabels(refPos: ReferencePosition): boolean {
|
|
51
|
+
return refGetRangeLabels(refPos) !== undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ReferencePosition {
|
|
55
|
+
properties?: PropertySet;
|
|
56
|
+
refType: ReferenceType;
|
|
57
|
+
|
|
58
|
+
getSegment(): ISegment | undefined;
|
|
59
|
+
getOffset(): number;
|
|
60
|
+
addProperties(newProps: PropertySet, op?: ICombiningOp): void;
|
|
61
|
+
isLeaf(): boolean;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @deprecated - use refHasTileLabels
|
|
65
|
+
*/
|
|
66
|
+
hasTileLabels(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated - use refHasRangeLabels
|
|
69
|
+
*/
|
|
70
|
+
hasRangeLabels(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* @deprecated - use refHasTileLabel
|
|
73
|
+
*/
|
|
74
|
+
hasTileLabel(label: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* @deprecated - use refHasRangeLabel
|
|
77
|
+
*/
|
|
78
|
+
hasRangeLabel(label: string): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* @deprecated - use refGetTileLabels
|
|
81
|
+
*/
|
|
82
|
+
getTileLabels(): string[] | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* @deprecated - use refGetRangeLabels
|
|
85
|
+
*/
|
|
86
|
+
getRangeLabels(): string[] | undefined;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type RangeStackMap = MapLike<Stack<ReferencePosition>>;
|
|
90
|
+
export const DetachedReferencePosition = -1;
|
|
91
|
+
|
|
92
|
+
export function minReferencePosition<T extends ReferencePosition>(a: T, b: T): T {
|
|
93
|
+
if (compareReferencePositions(a, b) < 0) {
|
|
94
|
+
return a;
|
|
95
|
+
} else {
|
|
96
|
+
return b;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function maxReferencePosition<T extends ReferencePosition>(a: T, b: T): T {
|
|
101
|
+
if (compareReferencePositions(a, b) > 0) {
|
|
102
|
+
return a;
|
|
103
|
+
} else {
|
|
104
|
+
return b;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function compareReferencePositions(a: ReferencePosition, b: ReferencePosition): number {
|
|
109
|
+
const aSeg = a.getSegment();
|
|
110
|
+
const bSeg = b.getSegment();
|
|
111
|
+
if (aSeg === bSeg) {
|
|
112
|
+
return a.getOffset() - b.getOffset();
|
|
113
|
+
} else {
|
|
114
|
+
if (aSeg === undefined
|
|
115
|
+
|| (bSeg !== undefined &&
|
|
116
|
+
aSeg.ordinal < bSeg.ordinal)) {
|
|
117
|
+
return -1;
|
|
118
|
+
} else {
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/snapshotChunks.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type JsonSegmentSpecs = IJSONSegment | IJSONSegmentWithMergeInfo;
|
|
|
20
20
|
|
|
21
21
|
export interface MergeTreeChunkLegacy extends VersionedMergeTreeChunk {
|
|
22
22
|
version: undefined;
|
|
23
|
-
chunkStartSegmentIndex: number
|
|
23
|
+
chunkStartSegmentIndex: number;
|
|
24
24
|
chunkSegmentCount: number;
|
|
25
25
|
chunkLengthChars: number;
|
|
26
26
|
totalLengthChars?: number;
|
|
@@ -32,19 +32,19 @@ export interface MergeTreeChunkLegacy extends VersionedMergeTreeChunk {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export interface MergeTreeHeaderChunkMetadata {
|
|
35
|
-
id: string
|
|
35
|
+
id: string;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export interface MergeTreeHeaderMetadata {
|
|
39
|
-
totalLength: number
|
|
40
|
-
totalSegmentCount: number
|
|
41
|
-
orderedChunkMetadata: MergeTreeHeaderChunkMetadata[]
|
|
42
|
-
sequenceNumber: number
|
|
43
|
-
minSequenceNumber: number
|
|
39
|
+
totalLength: number;
|
|
40
|
+
totalSegmentCount: number;
|
|
41
|
+
orderedChunkMetadata: MergeTreeHeaderChunkMetadata[];
|
|
42
|
+
sequenceNumber: number;
|
|
43
|
+
minSequenceNumber: number;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export interface MergeTreeChunkV1 extends VersionedMergeTreeChunk {
|
|
47
|
-
version: "1"
|
|
47
|
+
version: "1";
|
|
48
48
|
startIndex: number;
|
|
49
49
|
segmentCount: number;
|
|
50
50
|
length: number;
|
package/src/snapshotLoader.ts
CHANGED
|
@@ -38,18 +38,18 @@ export class SnapshotLoader {
|
|
|
38
38
|
|
|
39
39
|
public async initialize(
|
|
40
40
|
services: IChannelStorageService,
|
|
41
|
-
): Promise<{ catchupOpsP: Promise<ISequencedDocumentMessage[]
|
|
41
|
+
): Promise<{ catchupOpsP: Promise<ISequencedDocumentMessage[]>; }> {
|
|
42
42
|
const headerLoadedP =
|
|
43
43
|
services.readBlob(SnapshotLegacy.header).then((header) => {
|
|
44
44
|
assert(!!header, 0x05f /* "Missing blob header on legacy snapshot!" */);
|
|
45
|
-
return this.loadHeader(bufferToString(header,"utf8"));
|
|
45
|
+
return this.loadHeader(bufferToString(header, "utf8"));
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
const catchupOpsP =
|
|
49
49
|
this.loadBodyAndCatchupOps(headerLoadedP, services);
|
|
50
50
|
|
|
51
51
|
catchupOpsP.catch(
|
|
52
|
-
(err)=>this.logger.sendErrorEvent({ eventName: "CatchupOpsLoadFailure" },err));
|
|
52
|
+
(err) => this.logger.sendErrorEvent({ eventName: "CatchupOpsLoadFailure" }, err));
|
|
53
53
|
|
|
54
54
|
await headerLoadedP;
|
|
55
55
|
|
|
@@ -111,7 +111,7 @@ export class SnapshotLoader {
|
|
|
111
111
|
}
|
|
112
112
|
if (spec.removedClientIds !== undefined) {
|
|
113
113
|
seg.removedClientIds = spec.removedClientIds?.map(
|
|
114
|
-
(sid)=> this.client.getOrAddShortClientId(sid));
|
|
114
|
+
(sid) => this.client.getOrAddShortClientId(sid));
|
|
115
115
|
}
|
|
116
116
|
} else {
|
|
117
117
|
seg = this.client.specToSegment(spec);
|
package/src/snapshotV1.ts
CHANGED
|
@@ -225,7 +225,7 @@ export class SnapshotV1 {
|
|
|
225
225
|
? this.getLongClientId(segment.removedClientIds[0])
|
|
226
226
|
: undefined;
|
|
227
227
|
|
|
228
|
-
raw.removedClientIds = segment.removedClientIds?.map((id)=>this.getLongClientId(id));
|
|
228
|
+
raw.removedClientIds = segment.removedClientIds?.map((id) => this.getLongClientId(id));
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
// Sanity check that we are preserving either the seq < minSeq or a removed segment's info.
|
package/src/snapshotlegacy.ts
CHANGED
|
@@ -131,7 +131,7 @@ export class SnapshotLegacy {
|
|
|
131
131
|
segments === chunk1.totalSegmentCount,
|
|
132
132
|
0x05e /* "emit: mismatch in totalSegmentCount" */);
|
|
133
133
|
|
|
134
|
-
if(catchUpMsgs !== undefined && catchUpMsgs.length > 0) {
|
|
134
|
+
if (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {
|
|
135
135
|
builder.addBlob(
|
|
136
136
|
this.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,
|
|
137
137
|
serializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs));
|
package/src/sortedSegmentSet.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { ISegment } from "./mergeTree";
|
|
|
15
15
|
* the segments changes. This invariant allows ensure the segments stay ordered and unique, and that new segments
|
|
16
16
|
* can be inserted into that order.
|
|
17
17
|
*/
|
|
18
|
-
export class SortedSegmentSet<T extends ISegment | { readonly segment: ISegment } = ISegment> {
|
|
18
|
+
export class SortedSegmentSet<T extends ISegment | { readonly segment: ISegment; } = ISegment> {
|
|
19
19
|
private readonly ordinalSortedItems: T[] = [];
|
|
20
20
|
|
|
21
21
|
public get size(): number {
|
|
@@ -52,7 +52,7 @@ export class SortedSegmentSet<T extends ISegment | { readonly segment: ISegment
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
private getOrdinal(item: T): string {
|
|
55
|
-
const maybeObject = item as { readonly segment: ISegment };
|
|
55
|
+
const maybeObject = item as { readonly segment: ISegment; };
|
|
56
56
|
if (maybeObject && maybeObject.segment) {
|
|
57
57
|
return maybeObject.segment.ordinal;
|
|
58
58
|
}
|
|
@@ -61,7 +61,7 @@ export class SortedSegmentSet<T extends ISegment | { readonly segment: ISegment
|
|
|
61
61
|
return maybeSegment.ordinal;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
private findOrdinalPosition(ordinal: string, start?: number, end?: number): { exists: boolean
|
|
64
|
+
private findOrdinalPosition(ordinal: string, start?: number, end?: number): { exists: boolean; index: number; } {
|
|
65
65
|
if (this.ordinalSortedItems.length === 0) {
|
|
66
66
|
return { exists: false, index: 0 };
|
|
67
67
|
}
|