mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
clock: Cleanup ReplicaId, Lamport and Global (#40600)
- Notable change is the use of a newtype for `ReplicaId` - Fixes `WorktreeStore::create_remote_worktree` creating a remote worktree with the local replica id, though this is not currently used - Fixes observing the `Agent` (that is following the agent) causing global clocks to allocate 65535 elements - Shrinks the size of `Global` a bit. In a local or non-collab remote session it won't ever allocate still. Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
parent
37e264ab99
commit
43a9368dff
33 changed files with 427 additions and 284 deletions
|
|
@ -236,21 +236,21 @@ impl PendingDiff {
|
|||
fn finalize(&self, cx: &mut Context<Diff>) -> FinalizedDiff {
|
||||
let ranges = self.excerpt_ranges(cx);
|
||||
let base_text = self.base_text.clone();
|
||||
let language_registry = self.new_buffer.read(cx).language_registry();
|
||||
let new_buffer = self.new_buffer.read(cx);
|
||||
let language_registry = new_buffer.language_registry();
|
||||
|
||||
let path = self
|
||||
.new_buffer
|
||||
.read(cx)
|
||||
let path = new_buffer
|
||||
.file()
|
||||
.map(|file| file.path().display(file.path_style(cx)))
|
||||
.unwrap_or("untitled".into())
|
||||
.into();
|
||||
let replica_id = new_buffer.replica_id();
|
||||
|
||||
// Replace the buffer in the multibuffer with the snapshot
|
||||
let buffer = cx.new(|cx| {
|
||||
let language = self.new_buffer.read(cx).language().cloned();
|
||||
let buffer = TextBuffer::new_normalized(
|
||||
0,
|
||||
replica_id,
|
||||
cx.entity_id().as_non_zero_u64().into(),
|
||||
self.new_buffer.read(cx).line_ending(),
|
||||
self.new_buffer.read(cx).as_rope().clone(),
|
||||
|
|
|
|||
|
|
@ -308,12 +308,13 @@ mod tests {
|
|||
use indoc::indoc;
|
||||
use language::{BufferId, TextBuffer};
|
||||
use rand::prelude::*;
|
||||
use text::ReplicaId;
|
||||
use util::test::{generate_marked_text, marked_text_ranges};
|
||||
|
||||
#[test]
|
||||
fn test_empty_query() {
|
||||
let buffer = TextBuffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
"Hello world\nThis is a test\nFoo bar baz",
|
||||
);
|
||||
|
|
@ -327,7 +328,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_streaming_exact_match() {
|
||||
let buffer = TextBuffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
"Hello world\nThis is a test\nFoo bar baz",
|
||||
);
|
||||
|
|
@ -351,7 +352,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_streaming_fuzzy_match() {
|
||||
let buffer = TextBuffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
indoc! {"
|
||||
function foo(a, b) {
|
||||
|
|
@ -385,7 +386,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_incremental_improvement() {
|
||||
let buffer = TextBuffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
"Line 1\nLine 2\nLine 3\nLine 4\nLine 5",
|
||||
);
|
||||
|
|
@ -410,7 +411,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_incomplete_lines_buffering() {
|
||||
let buffer = TextBuffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
indoc! {"
|
||||
The quick brown fox
|
||||
|
|
@ -437,7 +438,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_multiline_fuzzy_match() {
|
||||
let buffer = TextBuffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
indoc! {r#"
|
||||
impl Display for User {
|
||||
|
|
@ -691,7 +692,11 @@ mod tests {
|
|||
}
|
||||
"#};
|
||||
|
||||
let buffer = TextBuffer::new(0, BufferId::new(1).unwrap(), text.to_string());
|
||||
let buffer = TextBuffer::new(
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
text.to_string(),
|
||||
);
|
||||
let snapshot = buffer.snapshot();
|
||||
let mut matcher = StreamingFuzzyMatcher::new(snapshot.clone());
|
||||
|
||||
|
|
@ -724,7 +729,7 @@ mod tests {
|
|||
#[track_caller]
|
||||
fn assert_location_resolution(text_with_expected_range: &str, query: &str, rng: &mut StdRng) {
|
||||
let (text, expected_ranges) = marked_text_ranges(text_with_expected_range, false);
|
||||
let buffer = TextBuffer::new(0, BufferId::new(1).unwrap(), text.clone());
|
||||
let buffer = TextBuffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), text.clone());
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let mut matcher = StreamingFuzzyMatcher::new(snapshot);
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ pub enum ContextSummary {
|
|||
Error,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ContextSummaryContent {
|
||||
pub text: String,
|
||||
pub done: bool,
|
||||
|
|
@ -523,7 +523,11 @@ impl ContextSummary {
|
|||
match self {
|
||||
ContextSummary::Content(content) => content,
|
||||
ContextSummary::Pending | ContextSummary::Error => {
|
||||
let content = ContextSummaryContent::default();
|
||||
let content = ContextSummaryContent {
|
||||
text: "".to_string(),
|
||||
done: false,
|
||||
timestamp: clock::Lamport::MIN,
|
||||
};
|
||||
*self = ContextSummary::Content(content);
|
||||
self.content_as_mut().unwrap()
|
||||
}
|
||||
|
|
@ -796,7 +800,7 @@ impl AssistantContext {
|
|||
};
|
||||
|
||||
let first_message_id = MessageId(clock::Lamport {
|
||||
replica_id: 0,
|
||||
replica_id: ReplicaId::LOCAL,
|
||||
value: 0,
|
||||
});
|
||||
let message = MessageAnchor {
|
||||
|
|
@ -2692,7 +2696,7 @@ impl AssistantContext {
|
|||
self.summary = ContextSummary::Content(ContextSummaryContent {
|
||||
text: "".to_string(),
|
||||
done: false,
|
||||
timestamp: clock::Lamport::default(),
|
||||
timestamp: clock::Lamport::MIN,
|
||||
});
|
||||
replace_old = true;
|
||||
}
|
||||
|
|
@ -3117,7 +3121,7 @@ impl SavedContext {
|
|||
|
||||
let mut first_message_metadata = None;
|
||||
for message in self.messages {
|
||||
if message.id == MessageId(clock::Lamport::default()) {
|
||||
if message.id == MessageId(clock::Lamport::MIN) {
|
||||
first_message_metadata = Some(message.metadata);
|
||||
} else {
|
||||
operations.push(ContextOperation::InsertMessage {
|
||||
|
|
@ -3141,7 +3145,7 @@ impl SavedContext {
|
|||
if let Some(metadata) = first_message_metadata {
|
||||
let timestamp = next_timestamp.tick();
|
||||
operations.push(ContextOperation::UpdateMessage {
|
||||
message_id: MessageId(clock::Lamport::default()),
|
||||
message_id: MessageId(clock::Lamport::MIN),
|
||||
metadata: MessageMetadata {
|
||||
role: metadata.role,
|
||||
status: metadata.status,
|
||||
|
|
|
|||
|
|
@ -741,7 +741,7 @@ async fn test_serialization(cx: &mut TestAppContext) {
|
|||
);
|
||||
}
|
||||
|
||||
#[gpui::test(iterations = 100)]
|
||||
#[gpui::test(iterations = 25)]
|
||||
async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: StdRng) {
|
||||
cx.update(init_test);
|
||||
|
||||
|
|
@ -771,7 +771,7 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
|
|||
let context = cx.new(|cx| {
|
||||
AssistantContext::new(
|
||||
context_id.clone(),
|
||||
i as ReplicaId,
|
||||
ReplicaId::new(i as u16),
|
||||
language::Capability::ReadWrite,
|
||||
registry.clone(),
|
||||
prompt_builder.clone(),
|
||||
|
|
@ -789,7 +789,7 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
|
|||
if let ContextEvent::Operation(op) = event {
|
||||
network
|
||||
.lock()
|
||||
.broadcast(i as ReplicaId, vec![op.to_proto()]);
|
||||
.broadcast(ReplicaId::new(i as u16), vec![op.to_proto()]);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -797,7 +797,7 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
|
|||
});
|
||||
|
||||
contexts.push(context);
|
||||
network.lock().add_peer(i as ReplicaId);
|
||||
network.lock().add_peer(ReplicaId::new(i as u16));
|
||||
}
|
||||
|
||||
let mut mutation_count = operations;
|
||||
|
|
@ -943,9 +943,9 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
|
|||
mutation_count -= 1;
|
||||
}
|
||||
_ => {
|
||||
let replica_id = context_index as ReplicaId;
|
||||
let replica_id = ReplicaId::new(context_index as u16);
|
||||
if network.lock().is_disconnected(replica_id) {
|
||||
network.lock().reconnect_peer(replica_id, 0);
|
||||
network.lock().reconnect_peer(replica_id, ReplicaId::new(0));
|
||||
|
||||
let (ops_to_send, ops_to_receive) = cx.read(|cx| {
|
||||
let host_context = &contexts[0].read(cx);
|
||||
|
|
@ -971,7 +971,7 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
|
|||
|
||||
network.lock().broadcast(replica_id, ops_to_send);
|
||||
context.update(cx, |context, cx| context.apply_ops(ops_to_receive, cx));
|
||||
} else if rng.random_bool(0.1) && replica_id != 0 {
|
||||
} else if rng.random_bool(0.1) && replica_id != ReplicaId::new(0) {
|
||||
log::info!("Context {}: disconnecting", context_index);
|
||||
network.lock().disconnect_peer(replica_id);
|
||||
} else if network.lock().has_unreceived(replica_id) {
|
||||
|
|
@ -996,25 +996,25 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
|
|||
assert_eq!(
|
||||
context.buffer.read(cx).text(),
|
||||
first_context.buffer.read(cx).text(),
|
||||
"Context {} text != Context 0 text",
|
||||
"Context {:?} text != Context 0 text",
|
||||
context.buffer.read(cx).replica_id()
|
||||
);
|
||||
assert_eq!(
|
||||
context.message_anchors,
|
||||
first_context.message_anchors,
|
||||
"Context {} messages != Context 0 messages",
|
||||
"Context {:?} messages != Context 0 messages",
|
||||
context.buffer.read(cx).replica_id()
|
||||
);
|
||||
assert_eq!(
|
||||
context.messages_metadata,
|
||||
first_context.messages_metadata,
|
||||
"Context {} message metadata != Context 0 message metadata",
|
||||
"Context {:?} message metadata != Context 0 message metadata",
|
||||
context.buffer.read(cx).replica_id()
|
||||
);
|
||||
assert_eq!(
|
||||
context.slash_command_output_sections,
|
||||
first_context.slash_command_output_sections,
|
||||
"Context {} slash command output sections != Context 0 slash command output sections",
|
||||
"Context {:?} slash command output sections != Context 0 slash command output sections",
|
||||
context.buffer.read(cx).replica_id()
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ struct PendingHunk {
|
|||
new_status: DiffHunkSecondaryStatus,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DiffHunkSummary {
|
||||
buffer_range: Range<Anchor>,
|
||||
}
|
||||
|
|
@ -114,7 +114,9 @@ impl sum_tree::Summary for DiffHunkSummary {
|
|||
type Context<'a> = &'a text::BufferSnapshot;
|
||||
|
||||
fn zero(_cx: Self::Context<'_>) -> Self {
|
||||
Default::default()
|
||||
DiffHunkSummary {
|
||||
buffer_range: Anchor::MIN..Anchor::MIN,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, other: &Self, buffer: Self::Context<'_>) {
|
||||
|
|
@ -937,7 +939,9 @@ impl BufferDiff {
|
|||
|
||||
pub fn clear_pending_hunks(&mut self, cx: &mut Context<Self>) {
|
||||
if self.secondary_diff.is_some() {
|
||||
self.inner.pending_hunks = SumTree::from_summary(DiffHunkSummary::default());
|
||||
self.inner.pending_hunks = SumTree::from_summary(DiffHunkSummary {
|
||||
buffer_range: Anchor::MIN..Anchor::MIN,
|
||||
});
|
||||
cx.emit(BufferDiffEvent::DiffChanged {
|
||||
changed_range: Some(Anchor::MIN..Anchor::MAX),
|
||||
});
|
||||
|
|
@ -1368,7 +1372,7 @@ mod tests {
|
|||
use gpui::TestAppContext;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
use rand::{Rng as _, rngs::StdRng};
|
||||
use text::{Buffer, BufferId, Rope};
|
||||
use text::{Buffer, BufferId, ReplicaId, Rope};
|
||||
use unindent::Unindent as _;
|
||||
use util::test::marked_text_ranges;
|
||||
|
||||
|
|
@ -1393,7 +1397,7 @@ mod tests {
|
|||
"
|
||||
.unindent();
|
||||
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text);
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
|
||||
let mut diff = BufferDiffSnapshot::new_sync(buffer.clone(), diff_base.clone(), cx);
|
||||
assert_hunks(
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &buffer),
|
||||
|
|
@ -1467,7 +1471,7 @@ mod tests {
|
|||
"
|
||||
.unindent();
|
||||
|
||||
let buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
|
||||
let unstaged_diff = BufferDiffSnapshot::new_sync(buffer.clone(), index_text, cx);
|
||||
let mut uncommitted_diff =
|
||||
BufferDiffSnapshot::new_sync(buffer.clone(), head_text.clone(), cx);
|
||||
|
|
@ -1536,7 +1540,7 @@ mod tests {
|
|||
"
|
||||
.unindent();
|
||||
|
||||
let buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
|
||||
let diff = cx
|
||||
.update(|cx| {
|
||||
BufferDiffSnapshot::new_with_base_text(
|
||||
|
|
@ -1799,7 +1803,7 @@ mod tests {
|
|||
|
||||
for example in table {
|
||||
let (buffer_text, ranges) = marked_text_ranges(&example.buffer_marked_text, false);
|
||||
let buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
|
||||
let hunk_range =
|
||||
buffer.anchor_before(ranges[0].start)..buffer.anchor_before(ranges[0].end);
|
||||
|
||||
|
|
@ -1872,7 +1876,11 @@ mod tests {
|
|||
"
|
||||
.unindent();
|
||||
|
||||
let buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text.clone());
|
||||
let buffer = Buffer::new(
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
buffer_text.clone(),
|
||||
);
|
||||
let unstaged = BufferDiffSnapshot::new_sync(buffer.clone(), index_text, cx);
|
||||
let uncommitted = BufferDiffSnapshot::new_sync(buffer.clone(), head_text.clone(), cx);
|
||||
let unstaged_diff = cx.new(|cx| {
|
||||
|
|
@ -1945,7 +1953,7 @@ mod tests {
|
|||
"
|
||||
.unindent();
|
||||
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), buffer_text_1);
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text_1);
|
||||
|
||||
let empty_diff = cx.update(|cx| BufferDiffSnapshot::empty(&buffer, cx));
|
||||
let diff_1 = BufferDiffSnapshot::new_sync(buffer.clone(), base_text.clone(), cx);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rpc::{
|
|||
proto::{self, PeerId},
|
||||
};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use text::BufferId;
|
||||
use text::{BufferId, ReplicaId};
|
||||
use util::ResultExt;
|
||||
|
||||
pub const ACKNOWLEDGE_DEBOUNCE_INTERVAL: Duration = Duration::from_millis(250);
|
||||
|
|
@ -65,7 +65,12 @@ impl ChannelBuffer {
|
|||
|
||||
let buffer = cx.new(|cx| {
|
||||
let capability = channel_store.read(cx).channel_capability(channel.id);
|
||||
language::Buffer::remote(buffer_id, response.replica_id as u16, capability, base_text)
|
||||
language::Buffer::remote(
|
||||
buffer_id,
|
||||
ReplicaId::new(response.replica_id as u16),
|
||||
capability,
|
||||
base_text,
|
||||
)
|
||||
})?;
|
||||
buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx))?;
|
||||
|
||||
|
|
@ -272,7 +277,7 @@ impl ChannelBuffer {
|
|||
self.connected
|
||||
}
|
||||
|
||||
pub fn replica_id(&self, cx: &App) -> u16 {
|
||||
pub fn replica_id(&self, cx: &App) -> ReplicaId {
|
||||
self.buffer.read(cx).replica_id()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -943,7 +943,7 @@ impl Collaborator {
|
|||
pub fn from_proto(message: proto::Collaborator) -> Result<Self> {
|
||||
Ok(Self {
|
||||
peer_id: message.peer_id.context("invalid peer id")?,
|
||||
replica_id: message.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(message.replica_id as u16),
|
||||
user_id: message.user_id as UserId,
|
||||
is_host: message.is_host,
|
||||
committer_name: message.committer_name,
|
||||
|
|
|
|||
|
|
@ -4,33 +4,73 @@ use serde::{Deserialize, Serialize};
|
|||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
fmt, iter,
|
||||
fmt,
|
||||
};
|
||||
|
||||
pub use system_clock::*;
|
||||
|
||||
pub const LOCAL_BRANCH_REPLICA_ID: u16 = u16::MAX;
|
||||
pub const AGENT_REPLICA_ID: u16 = u16::MAX - 1;
|
||||
|
||||
/// A unique identifier for each distributed node.
|
||||
pub type ReplicaId = u16;
|
||||
#[derive(Clone, Copy, Default, Eq, Hash, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct ReplicaId(u16);
|
||||
|
||||
impl ReplicaId {
|
||||
/// The local replica
|
||||
pub const LOCAL: ReplicaId = ReplicaId(0);
|
||||
/// The remote replica of the connected remote server.
|
||||
pub const REMOTE_SERVER: ReplicaId = ReplicaId(1);
|
||||
/// The agent's unique identifier.
|
||||
pub const AGENT: ReplicaId = ReplicaId(2);
|
||||
/// A local branch.
|
||||
pub const LOCAL_BRANCH: ReplicaId = ReplicaId(3);
|
||||
/// The first collaborative replica ID, any replica equal or greater than this is a collaborative replica.
|
||||
pub const FIRST_COLLAB_ID: ReplicaId = ReplicaId(Self::LOCAL_BRANCH.0 + 1);
|
||||
|
||||
pub fn new(id: u16) -> Self {
|
||||
ReplicaId(id)
|
||||
}
|
||||
|
||||
pub fn as_u16(&self) -> u16 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_remote(self) -> bool {
|
||||
self == ReplicaId::REMOTE_SERVER || self >= ReplicaId::FIRST_COLLAB_ID
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReplicaId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if *self == ReplicaId::LOCAL {
|
||||
write!(f, "<local>")
|
||||
} else if *self == ReplicaId::REMOTE_SERVER {
|
||||
write!(f, "<remote>")
|
||||
} else if *self == ReplicaId::AGENT {
|
||||
write!(f, "<agent>")
|
||||
} else if *self == ReplicaId::LOCAL_BRANCH {
|
||||
write!(f, "<branch>")
|
||||
} else {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [Lamport sequence number](https://en.wikipedia.org/wiki/Lamport_timestamp).
|
||||
pub type Seq = u32;
|
||||
|
||||
/// A [Lamport timestamp](https://en.wikipedia.org/wiki/Lamport_timestamp),
|
||||
/// used to determine the ordering of events in the editor.
|
||||
#[derive(Clone, Copy, Default, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Lamport {
|
||||
pub replica_id: ReplicaId,
|
||||
pub value: Seq,
|
||||
}
|
||||
|
||||
/// A [vector clock](https://en.wikipedia.org/wiki/Vector_clock).
|
||||
/// A [version vector](https://en.wikipedia.org/wiki/Version_vector).
|
||||
#[derive(Clone, Default, Hash, Eq, PartialEq)]
|
||||
pub struct Global {
|
||||
values: SmallVec<[u32; 8]>,
|
||||
local_branch_value: u32,
|
||||
// 4 is chosen as it is the biggest count that does not increase the size of the field itself.
|
||||
// Coincidentally, it also covers all the important non-collab replica ids.
|
||||
values: SmallVec<[u32; 4]>,
|
||||
}
|
||||
|
||||
impl Global {
|
||||
|
|
@ -38,30 +78,31 @@ impl Global {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
/// Fetches the sequence number for the given replica ID.
|
||||
pub fn get(&self, replica_id: ReplicaId) -> Seq {
|
||||
if replica_id == LOCAL_BRANCH_REPLICA_ID {
|
||||
self.local_branch_value
|
||||
} else {
|
||||
self.values.get(replica_id as usize).copied().unwrap_or(0) as Seq
|
||||
}
|
||||
self.values.get(replica_id.0 as usize).copied().unwrap_or(0) as Seq
|
||||
}
|
||||
|
||||
/// Observe the lamport timestampe.
|
||||
///
|
||||
/// This sets the current sequence number of the observed replica ID to the maximum of this global's observed sequence and the observed timestamp.
|
||||
pub fn observe(&mut self, timestamp: Lamport) {
|
||||
debug_assert_ne!(timestamp.replica_id, Lamport::MAX.replica_id);
|
||||
if timestamp.value > 0 {
|
||||
if timestamp.replica_id == LOCAL_BRANCH_REPLICA_ID {
|
||||
self.local_branch_value = cmp::max(self.local_branch_value, timestamp.value);
|
||||
} else {
|
||||
let new_len = timestamp.replica_id as usize + 1;
|
||||
if new_len > self.values.len() {
|
||||
self.values.resize(new_len, 0);
|
||||
}
|
||||
|
||||
let entry = &mut self.values[timestamp.replica_id as usize];
|
||||
*entry = cmp::max(*entry, timestamp.value);
|
||||
let new_len = timestamp.replica_id.0 as usize + 1;
|
||||
if new_len > self.values.len() {
|
||||
self.values.resize(new_len, 0);
|
||||
}
|
||||
|
||||
let entry = &mut self.values[timestamp.replica_id.0 as usize];
|
||||
*entry = cmp::max(*entry, timestamp.value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Join another global.
|
||||
///
|
||||
/// This observes all timestamps from the other global.
|
||||
#[doc(alias = "synchronize")]
|
||||
pub fn join(&mut self, other: &Self) {
|
||||
if other.values.len() > self.values.len() {
|
||||
self.values.resize(other.values.len(), 0);
|
||||
|
|
@ -70,34 +111,36 @@ impl Global {
|
|||
for (left, right) in self.values.iter_mut().zip(&other.values) {
|
||||
*left = cmp::max(*left, *right);
|
||||
}
|
||||
|
||||
self.local_branch_value = cmp::max(self.local_branch_value, other.local_branch_value);
|
||||
}
|
||||
|
||||
/// Meet another global.
|
||||
///
|
||||
/// Sets all unobserved timestamps of this global to the sequences of other and sets all observed timestamps of this global to the minimum observed of both globals.
|
||||
pub fn meet(&mut self, other: &Self) {
|
||||
if other.values.len() > self.values.len() {
|
||||
self.values.resize(other.values.len(), 0);
|
||||
}
|
||||
|
||||
let mut new_len = 0;
|
||||
for (ix, (left, right)) in self
|
||||
.values
|
||||
.iter_mut()
|
||||
.zip(other.values.iter().chain(iter::repeat(&0)))
|
||||
.enumerate()
|
||||
{
|
||||
if *left == 0 {
|
||||
*left = *right;
|
||||
} else if *right > 0 {
|
||||
*left = cmp::min(*left, *right);
|
||||
for (ix, (left, &right)) in self.values.iter_mut().zip(&other.values).enumerate() {
|
||||
match (*left, right) {
|
||||
// left has not observed the replica
|
||||
(0, _) => *left = right,
|
||||
// right has not observed the replica
|
||||
(_, 0) => (),
|
||||
(_, _) => *left = cmp::min(*left, right),
|
||||
}
|
||||
|
||||
if *left != 0 {
|
||||
new_len = ix + 1;
|
||||
}
|
||||
}
|
||||
self.values.resize(new_len, 0);
|
||||
self.local_branch_value = cmp::min(self.local_branch_value, other.local_branch_value);
|
||||
if other.values.len() == self.values.len() {
|
||||
// only truncate if other was equal or shorter (which at this point
|
||||
// cant be due to the resize above) to `self` as otherwise we would
|
||||
// truncate the unprocessed tail that is guaranteed to contain
|
||||
// non-null timestamps
|
||||
self.values.truncate(new_len);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn observed(&self, timestamp: Lamport) -> bool {
|
||||
|
|
@ -105,20 +148,18 @@ impl Global {
|
|||
}
|
||||
|
||||
pub fn observed_any(&self, other: &Self) -> bool {
|
||||
self.values
|
||||
.iter()
|
||||
.zip(other.values.iter())
|
||||
.any(|(left, right)| *right > 0 && left >= right)
|
||||
|| (other.local_branch_value > 0 && self.local_branch_value >= other.local_branch_value)
|
||||
self.iter()
|
||||
.zip(other.iter())
|
||||
.any(|(left, right)| right.value > 0 && left.value >= right.value)
|
||||
}
|
||||
|
||||
pub fn observed_all(&self, other: &Self) -> bool {
|
||||
let mut rhs = other.values.iter();
|
||||
self.values.iter().all(|left| match rhs.next() {
|
||||
Some(right) => left >= right,
|
||||
None => true,
|
||||
}) && rhs.next().is_none()
|
||||
&& self.local_branch_value >= other.local_branch_value
|
||||
if self.values.len() < other.values.len() {
|
||||
return false;
|
||||
}
|
||||
self.iter()
|
||||
.zip(other.iter())
|
||||
.all(|(left, right)| left.value >= right.value)
|
||||
}
|
||||
|
||||
pub fn changed_since(&self, other: &Self) -> bool {
|
||||
|
|
@ -128,21 +169,21 @@ impl Global {
|
|||
.iter()
|
||||
.zip(other.values.iter())
|
||||
.any(|(left, right)| left > right)
|
||||
|| self.local_branch_value > other.local_branch_value
|
||||
}
|
||||
|
||||
pub fn most_recent(&self) -> Option<Lamport> {
|
||||
self.iter().max_by_key(|timestamp| timestamp.value)
|
||||
}
|
||||
|
||||
/// Iterates all replicas observed by this global as well as any unobserved replicas whose ID is lower than the highest observed replica.
|
||||
pub fn iter(&self) -> impl Iterator<Item = Lamport> + '_ {
|
||||
self.values
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(replica_id, seq)| Lamport {
|
||||
replica_id: replica_id as ReplicaId,
|
||||
replica_id: ReplicaId(replica_id as u16),
|
||||
value: *seq,
|
||||
})
|
||||
.chain((self.local_branch_value > 0).then_some(Lamport {
|
||||
replica_id: LOCAL_BRANCH_REPLICA_ID,
|
||||
value: self.local_branch_value,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,12 +214,12 @@ impl PartialOrd for Lamport {
|
|||
|
||||
impl Lamport {
|
||||
pub const MIN: Self = Self {
|
||||
replica_id: ReplicaId::MIN,
|
||||
replica_id: ReplicaId(u16::MIN),
|
||||
value: Seq::MIN,
|
||||
};
|
||||
|
||||
pub const MAX: Self = Self {
|
||||
replica_id: ReplicaId::MAX,
|
||||
replica_id: ReplicaId(u16::MAX),
|
||||
value: Seq::MAX,
|
||||
};
|
||||
|
||||
|
|
@ -190,7 +231,7 @@ impl Lamport {
|
|||
}
|
||||
|
||||
pub fn as_u64(self) -> u64 {
|
||||
((self.value as u64) << 32) | (self.replica_id as u64)
|
||||
((self.value as u64) << 32) | (self.replica_id.0 as u64)
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) -> Self {
|
||||
|
|
@ -211,7 +252,7 @@ impl fmt::Debug for Lamport {
|
|||
} else if *self == Self::MIN {
|
||||
write!(f, "Lamport {{MIN}}")
|
||||
} else {
|
||||
write!(f, "Lamport {{{}: {}}}", self.replica_id, self.value)
|
||||
write!(f, "Lamport {{{:?}: {}}}", self.replica_id, self.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,16 +261,10 @@ impl fmt::Debug for Global {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Global {{")?;
|
||||
for timestamp in self.iter() {
|
||||
if timestamp.replica_id > 0 {
|
||||
if timestamp.replica_id.0 > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
if timestamp.replica_id == LOCAL_BRANCH_REPLICA_ID {
|
||||
write!(f, "<branch>: {}", timestamp.value)?;
|
||||
} else if timestamp.replica_id == AGENT_REPLICA_ID {
|
||||
write!(f, "<agent>: {}", timestamp.value)?;
|
||||
} else {
|
||||
write!(f, "{}: {}", timestamp.replica_id, timestamp.value)?;
|
||||
}
|
||||
write!(f, "{:?}: {}", timestamp.replica_id, timestamp.value)?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ impl Database {
|
|||
.iter()
|
||||
.map(|c| c.replica_id)
|
||||
.collect::<HashSet<_>>();
|
||||
let mut replica_id = ReplicaId(0);
|
||||
let mut replica_id = ReplicaId(clock::ReplicaId::FIRST_COLLAB_ID.as_u16() as i32);
|
||||
while replica_ids.contains(&replica_id) {
|
||||
replica_id.0 += 1;
|
||||
replica_id = ReplicaId(replica_id.0 + 1);
|
||||
}
|
||||
let collaborator = channel_buffer_collaborator::ActiveModel {
|
||||
channel_id: ActiveValue::Set(channel_id),
|
||||
|
|
@ -203,7 +203,7 @@ impl Database {
|
|||
while let Some(row) = rows.next().await {
|
||||
let row = row?;
|
||||
let timestamp = clock::Lamport {
|
||||
replica_id: row.replica_id as u16,
|
||||
replica_id: clock::ReplicaId::new(row.replica_id as u16),
|
||||
value: row.lamport_timestamp as u32,
|
||||
};
|
||||
server_version.observe(timestamp);
|
||||
|
|
@ -701,7 +701,11 @@ impl Database {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let mut text_buffer = text::Buffer::new(0, text::BufferId::new(1).unwrap(), base_text);
|
||||
let mut text_buffer = text::Buffer::new(
|
||||
clock::ReplicaId::LOCAL,
|
||||
text::BufferId::new(1).unwrap(),
|
||||
base_text,
|
||||
);
|
||||
text_buffer.apply_ops(operations.into_iter().filter_map(operation_from_wire));
|
||||
|
||||
let base_text = text_buffer.text();
|
||||
|
|
@ -934,7 +938,7 @@ pub fn operation_from_wire(operation: proto::Operation) -> Option<text::Operatio
|
|||
match operation.variant? {
|
||||
proto::operation::Variant::Edit(edit) => Some(text::Operation::Edit(EditOperation {
|
||||
timestamp: clock::Lamport {
|
||||
replica_id: edit.replica_id as text::ReplicaId,
|
||||
replica_id: clock::ReplicaId::new(edit.replica_id as u16),
|
||||
value: edit.lamport_timestamp,
|
||||
},
|
||||
version: version_from_wire(&edit.version),
|
||||
|
|
@ -949,7 +953,7 @@ pub fn operation_from_wire(operation: proto::Operation) -> Option<text::Operatio
|
|||
})),
|
||||
proto::operation::Variant::Undo(undo) => Some(text::Operation::Undo(UndoOperation {
|
||||
timestamp: clock::Lamport {
|
||||
replica_id: undo.replica_id as text::ReplicaId,
|
||||
replica_id: clock::ReplicaId::new(undo.replica_id as u16),
|
||||
value: undo.lamport_timestamp,
|
||||
},
|
||||
version: version_from_wire(&undo.version),
|
||||
|
|
@ -959,7 +963,7 @@ pub fn operation_from_wire(operation: proto::Operation) -> Option<text::Operatio
|
|||
.map(|c| {
|
||||
(
|
||||
clock::Lamport {
|
||||
replica_id: c.replica_id as text::ReplicaId,
|
||||
replica_id: clock::ReplicaId::new(c.replica_id as u16),
|
||||
value: c.lamport_timestamp,
|
||||
},
|
||||
c.count,
|
||||
|
|
@ -975,7 +979,7 @@ fn version_from_wire(message: &[proto::VectorClockEntry]) -> clock::Global {
|
|||
let mut version = clock::Global::new();
|
||||
for entry in message {
|
||||
version.observe(clock::Lamport {
|
||||
replica_id: entry.replica_id as text::ReplicaId,
|
||||
replica_id: clock::ReplicaId::new(entry.replica_id as u16),
|
||||
value: entry.timestamp,
|
||||
});
|
||||
}
|
||||
|
|
@ -986,7 +990,7 @@ fn version_to_wire(version: &clock::Global) -> Vec<proto::VectorClockEntry> {
|
|||
let mut message = Vec::new();
|
||||
for entry in version.iter() {
|
||||
message.push(proto::VectorClockEntry {
|
||||
replica_id: entry.replica_id as u32,
|
||||
replica_id: entry.replica_id.as_u16() as u32,
|
||||
timestamp: entry.value,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,14 +91,18 @@ impl Database {
|
|||
.await?;
|
||||
}
|
||||
|
||||
let replica_id = if is_ssh_project { 1 } else { 0 };
|
||||
let replica_id = if is_ssh_project {
|
||||
clock::ReplicaId::REMOTE_SERVER
|
||||
} else {
|
||||
clock::ReplicaId::LOCAL
|
||||
};
|
||||
|
||||
project_collaborator::ActiveModel {
|
||||
project_id: ActiveValue::set(project.id),
|
||||
connection_id: ActiveValue::set(connection.id as i32),
|
||||
connection_server_id: ActiveValue::set(ServerId(connection.owner_id as i32)),
|
||||
user_id: ActiveValue::set(participant.user_id),
|
||||
replica_id: ActiveValue::set(ReplicaId(replica_id)),
|
||||
replica_id: ActiveValue::set(ReplicaId(replica_id.as_u16() as i32)),
|
||||
is_host: ActiveValue::set(true),
|
||||
id: ActiveValue::NotSet,
|
||||
committer_name: ActiveValue::Set(None),
|
||||
|
|
@ -841,7 +845,7 @@ impl Database {
|
|||
.iter()
|
||||
.map(|c| c.replica_id)
|
||||
.collect::<HashSet<_>>();
|
||||
let mut replica_id = ReplicaId(1);
|
||||
let mut replica_id = ReplicaId(clock::ReplicaId::FIRST_COLLAB_ID.as_u16() as i32);
|
||||
while replica_ids.contains(&replica_id) {
|
||||
replica_id.0 += 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::*;
|
||||
use crate::test_both_dbs;
|
||||
use language::proto::{self, serialize_version};
|
||||
use text::Buffer;
|
||||
use text::{Buffer, ReplicaId};
|
||||
|
||||
test_both_dbs!(
|
||||
test_channel_buffers,
|
||||
|
|
@ -70,7 +70,11 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut buffer_a = Buffer::new(0, text::BufferId::new(1).unwrap(), "".to_string());
|
||||
let mut buffer_a = Buffer::new(
|
||||
ReplicaId::new(0),
|
||||
text::BufferId::new(1).unwrap(),
|
||||
"".to_string(),
|
||||
);
|
||||
let operations = vec![
|
||||
buffer_a.edit([(0..0, "hello world")]),
|
||||
buffer_a.edit([(5..5, ", cruel")]),
|
||||
|
|
@ -95,7 +99,7 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
.unwrap();
|
||||
|
||||
let mut buffer_b = Buffer::new(
|
||||
0,
|
||||
ReplicaId::new(0),
|
||||
text::BufferId::new(1).unwrap(),
|
||||
buffer_response_b.base_text,
|
||||
);
|
||||
|
|
@ -124,7 +128,7 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
rpc::proto::Collaborator {
|
||||
user_id: a_id.to_proto(),
|
||||
peer_id: Some(rpc::proto::PeerId { id: 1, owner_id }),
|
||||
replica_id: 0,
|
||||
replica_id: ReplicaId::FIRST_COLLAB_ID.as_u16() as u32,
|
||||
is_host: false,
|
||||
committer_name: None,
|
||||
committer_email: None,
|
||||
|
|
@ -132,7 +136,7 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
rpc::proto::Collaborator {
|
||||
user_id: b_id.to_proto(),
|
||||
peer_id: Some(rpc::proto::PeerId { id: 2, owner_id }),
|
||||
replica_id: 1,
|
||||
replica_id: ReplicaId::FIRST_COLLAB_ID.as_u16() as u32 + 1,
|
||||
is_host: false,
|
||||
committer_name: None,
|
||||
committer_email: None,
|
||||
|
|
@ -228,7 +232,8 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
db.join_channel_buffer(channel, user_id, connection_id)
|
||||
let res = db
|
||||
.join_channel_buffer(channel, user_id, connection_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
@ -239,7 +244,7 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||
);
|
||||
|
||||
text_buffers.push(Buffer::new(
|
||||
0,
|
||||
ReplicaId::new(res.replica_id as u16),
|
||||
text::BufferId::new(1).unwrap(),
|
||||
"".to_string(),
|
||||
));
|
||||
|
|
@ -276,7 +281,12 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||
db.join_channel_buffer(buffers[1].channel_id, user_id, connection_id)
|
||||
.await
|
||||
.unwrap();
|
||||
text_buffers[1] = Buffer::new(1, text::BufferId::new(1).unwrap(), "def".to_string());
|
||||
let replica_id = text_buffers[1].replica_id();
|
||||
text_buffers[1] = Buffer::new(
|
||||
replica_id,
|
||||
text::BufferId::new(1).unwrap(),
|
||||
"def".to_string(),
|
||||
);
|
||||
update_buffer(
|
||||
buffers[1].channel_id,
|
||||
user_id,
|
||||
|
|
@ -304,20 +314,32 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||
rpc::proto::ChannelBufferVersion {
|
||||
channel_id: buffers[0].channel_id.to_proto(),
|
||||
epoch: 0,
|
||||
version: serialize_version(&text_buffers[0].version()),
|
||||
version: serialize_version(&text_buffers[0].version())
|
||||
.into_iter()
|
||||
.filter(
|
||||
|vector| vector.replica_id == text_buffers[0].replica_id().as_u16() as u32
|
||||
)
|
||||
.collect::<Vec<_>>(),
|
||||
},
|
||||
rpc::proto::ChannelBufferVersion {
|
||||
channel_id: buffers[1].channel_id.to_proto(),
|
||||
epoch: 1,
|
||||
version: serialize_version(&text_buffers[1].version())
|
||||
.into_iter()
|
||||
.filter(|vector| vector.replica_id == text_buffers[1].replica_id() as u32)
|
||||
.filter(
|
||||
|vector| vector.replica_id == text_buffers[1].replica_id().as_u16() as u32
|
||||
)
|
||||
.collect::<Vec<_>>(),
|
||||
},
|
||||
rpc::proto::ChannelBufferVersion {
|
||||
channel_id: buffers[2].channel_id.to_proto(),
|
||||
epoch: 0,
|
||||
version: serialize_version(&text_buffers[2].version()),
|
||||
version: serialize_version(&text_buffers[2].version())
|
||||
.into_iter()
|
||||
.filter(
|
||||
|vector| vector.replica_id == text_buffers[2].replica_id().as_u16() as u32
|
||||
)
|
||||
.collect::<Vec<_>>(),
|
||||
},
|
||||
]
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1278,7 +1278,7 @@ mod tests {
|
|||
Anchor::min(),
|
||||
&InlayHint {
|
||||
label: InlayHintLabel::String("a".to_string()),
|
||||
position: text::Anchor::default(),
|
||||
position: text::Anchor::MIN,
|
||||
padding_left: false,
|
||||
padding_right: false,
|
||||
tooltip: None,
|
||||
|
|
@ -1298,7 +1298,7 @@ mod tests {
|
|||
Anchor::min(),
|
||||
&InlayHint {
|
||||
label: InlayHintLabel::String("a".to_string()),
|
||||
position: text::Anchor::default(),
|
||||
position: text::Anchor::MIN,
|
||||
padding_left: true,
|
||||
padding_right: true,
|
||||
tooltip: None,
|
||||
|
|
@ -1318,7 +1318,7 @@ mod tests {
|
|||
Anchor::min(),
|
||||
&InlayHint {
|
||||
label: InlayHintLabel::String(" a ".to_string()),
|
||||
position: text::Anchor::default(),
|
||||
position: text::Anchor::MIN,
|
||||
padding_left: false,
|
||||
padding_right: false,
|
||||
tooltip: None,
|
||||
|
|
@ -1338,7 +1338,7 @@ mod tests {
|
|||
Anchor::min(),
|
||||
&InlayHint {
|
||||
label: InlayHintLabel::String(" a ".to_string()),
|
||||
position: text::Anchor::default(),
|
||||
position: text::Anchor::MIN,
|
||||
padding_left: true,
|
||||
padding_right: true,
|
||||
tooltip: None,
|
||||
|
|
@ -1361,7 +1361,7 @@ mod tests {
|
|||
Anchor::min(),
|
||||
&InlayHint {
|
||||
label: InlayHintLabel::String("🎨".to_string()),
|
||||
position: text::Anchor::default(),
|
||||
position: text::Anchor::MIN,
|
||||
padding_left: true,
|
||||
padding_right: true,
|
||||
tooltip: None,
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ use anyhow::{Context as _, Result, anyhow};
|
|||
use blink_manager::BlinkManager;
|
||||
use buffer_diff::DiffHunkStatus;
|
||||
use client::{Collaborator, ParticipantIndex, parse_zed_link};
|
||||
use clock::{AGENT_REPLICA_ID, ReplicaId};
|
||||
use clock::ReplicaId;
|
||||
use code_context_menus::{
|
||||
AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
|
||||
CompletionsMenu, ContextMenuOrigin,
|
||||
|
|
@ -1301,7 +1301,7 @@ enum SelectionHistoryMode {
|
|||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
struct HoveredCursor {
|
||||
replica_id: u16,
|
||||
replica_id: ReplicaId,
|
||||
selection_id: usize,
|
||||
}
|
||||
|
||||
|
|
@ -23482,7 +23482,7 @@ impl EditorSnapshot {
|
|||
self.buffer_snapshot()
|
||||
.selections_in_range(range, false)
|
||||
.filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
|
||||
if replica_id == AGENT_REPLICA_ID {
|
||||
if replica_id == ReplicaId::AGENT {
|
||||
Some(RemoteSelection {
|
||||
replica_id,
|
||||
selection,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use gpui::{
|
|||
};
|
||||
use language::{
|
||||
Anchor, Buffer, Capability, DiskState, File, LanguageRegistry, LineEnding, OffsetRangeExt as _,
|
||||
Point, Rope, TextBuffer,
|
||||
Point, ReplicaId, Rope, TextBuffer,
|
||||
};
|
||||
use multi_buffer::PathKey;
|
||||
use project::{Project, WorktreeId, git_store::Repository};
|
||||
|
|
@ -135,7 +135,7 @@ impl CommitView {
|
|||
});
|
||||
let buffer = cx.new(|cx| {
|
||||
let buffer = TextBuffer::new_normalized(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
cx.entity_id().as_non_zero_u64().into(),
|
||||
LineEnding::default(),
|
||||
format_commit(&commit).into(),
|
||||
|
|
@ -316,7 +316,7 @@ async fn build_buffer(
|
|||
};
|
||||
let buffer = cx.new(|cx| {
|
||||
let buffer = TextBuffer::new_normalized(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
cx.entity_id().as_non_zero_u64().into(),
|
||||
line_ending,
|
||||
text,
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ pub use crate::{
|
|||
proto,
|
||||
};
|
||||
use anyhow::{Context as _, Result};
|
||||
use clock::Lamport;
|
||||
pub use clock::ReplicaId;
|
||||
use clock::{AGENT_REPLICA_ID, Lamport};
|
||||
use collections::HashMap;
|
||||
use fs::MTime;
|
||||
use futures::channel::oneshot;
|
||||
|
|
@ -828,7 +828,11 @@ impl Buffer {
|
|||
/// Create a new buffer with the given base text.
|
||||
pub fn local<T: Into<String>>(base_text: T, cx: &Context<Self>) -> Self {
|
||||
Self::build(
|
||||
TextBuffer::new(0, cx.entity_id().as_non_zero_u64().into(), base_text.into()),
|
||||
TextBuffer::new(
|
||||
ReplicaId::LOCAL,
|
||||
cx.entity_id().as_non_zero_u64().into(),
|
||||
base_text.into(),
|
||||
),
|
||||
None,
|
||||
Capability::ReadWrite,
|
||||
)
|
||||
|
|
@ -842,7 +846,7 @@ impl Buffer {
|
|||
) -> Self {
|
||||
Self::build(
|
||||
TextBuffer::new_normalized(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
cx.entity_id().as_non_zero_u64().into(),
|
||||
line_ending,
|
||||
base_text_normalized,
|
||||
|
|
@ -991,10 +995,10 @@ impl Buffer {
|
|||
language: None,
|
||||
remote_selections: Default::default(),
|
||||
diagnostics: Default::default(),
|
||||
diagnostics_timestamp: Default::default(),
|
||||
diagnostics_timestamp: Lamport::MIN,
|
||||
completion_triggers: Default::default(),
|
||||
completion_triggers_per_language_server: Default::default(),
|
||||
completion_triggers_timestamp: Default::default(),
|
||||
completion_triggers_timestamp: Lamport::MIN,
|
||||
deferred_ops: OperationQueue::new(),
|
||||
has_conflict: false,
|
||||
change_bits: Default::default(),
|
||||
|
|
@ -1012,7 +1016,8 @@ impl Buffer {
|
|||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
async move {
|
||||
let text =
|
||||
TextBuffer::new_normalized(0, buffer_id, Default::default(), text).snapshot();
|
||||
TextBuffer::new_normalized(ReplicaId::LOCAL, buffer_id, Default::default(), text)
|
||||
.snapshot();
|
||||
let mut syntax = SyntaxMap::new(&text).snapshot();
|
||||
if let Some(language) = language.clone() {
|
||||
let language_registry = language_registry.clone();
|
||||
|
|
@ -1033,8 +1038,13 @@ impl Buffer {
|
|||
pub fn build_empty_snapshot(cx: &mut App) -> BufferSnapshot {
|
||||
let entity_id = cx.reserve_entity::<Self>().entity_id();
|
||||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
let text =
|
||||
TextBuffer::new_normalized(0, buffer_id, Default::default(), Rope::new()).snapshot();
|
||||
let text = TextBuffer::new_normalized(
|
||||
ReplicaId::LOCAL,
|
||||
buffer_id,
|
||||
Default::default(),
|
||||
Rope::new(),
|
||||
)
|
||||
.snapshot();
|
||||
let syntax = SyntaxMap::new(&text).snapshot();
|
||||
BufferSnapshot {
|
||||
text,
|
||||
|
|
@ -1056,7 +1066,9 @@ impl Buffer {
|
|||
) -> BufferSnapshot {
|
||||
let entity_id = cx.reserve_entity::<Self>().entity_id();
|
||||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
let text = TextBuffer::new_normalized(0, buffer_id, Default::default(), text).snapshot();
|
||||
let text =
|
||||
TextBuffer::new_normalized(ReplicaId::LOCAL, buffer_id, Default::default(), text)
|
||||
.snapshot();
|
||||
let mut syntax = SyntaxMap::new(&text).snapshot();
|
||||
if let Some(language) = language.clone() {
|
||||
syntax.reparse(&text, language_registry, language);
|
||||
|
|
@ -2260,7 +2272,7 @@ impl Buffer {
|
|||
) {
|
||||
let lamport_timestamp = self.text.lamport_clock.tick();
|
||||
self.remote_selections.insert(
|
||||
AGENT_REPLICA_ID,
|
||||
ReplicaId::AGENT,
|
||||
SelectionSet {
|
||||
selections,
|
||||
lamport_timestamp,
|
||||
|
|
@ -2917,7 +2929,7 @@ impl Buffer {
|
|||
|
||||
edits.push((range, new_text));
|
||||
}
|
||||
log::info!("mutating buffer {} with {:?}", self.replica_id(), edits);
|
||||
log::info!("mutating buffer {:?} with {:?}", self.replica_id(), edits);
|
||||
self.edit(edits, None, cx);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,13 @@ fn test_line_endings(cx: &mut gpui::App) {
|
|||
fn test_set_line_ending(cx: &mut TestAppContext) {
|
||||
let base = cx.new(|cx| Buffer::local("one\ntwo\nthree\n", cx));
|
||||
let base_replica = cx.new(|cx| {
|
||||
Buffer::from_proto(1, Capability::ReadWrite, base.read(cx).to_proto(cx), None).unwrap()
|
||||
Buffer::from_proto(
|
||||
ReplicaId::new(1),
|
||||
Capability::ReadWrite,
|
||||
base.read(cx).to_proto(cx),
|
||||
None,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
base.update(cx, |_buffer, cx| {
|
||||
cx.subscribe(&base_replica, |this, _, event, cx| {
|
||||
|
|
@ -397,7 +403,7 @@ fn test_edit_events(cx: &mut gpui::App) {
|
|||
let buffer2 = cx.new(|cx| {
|
||||
Buffer::remote(
|
||||
BufferId::from(cx.entity_id().as_non_zero_u64()),
|
||||
1,
|
||||
ReplicaId::new(1),
|
||||
Capability::ReadWrite,
|
||||
"abcdef",
|
||||
)
|
||||
|
|
@ -2775,7 +2781,8 @@ fn test_serialization(cx: &mut gpui::App) {
|
|||
.background_executor()
|
||||
.block(buffer1.read(cx).serialize_ops(None, cx));
|
||||
let buffer2 = cx.new(|cx| {
|
||||
let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
|
||||
let mut buffer =
|
||||
Buffer::from_proto(ReplicaId::new(1), Capability::ReadWrite, state, None).unwrap();
|
||||
buffer.apply_ops(
|
||||
ops.into_iter()
|
||||
.map(|op| proto::deserialize_operation(op).unwrap()),
|
||||
|
|
@ -2794,7 +2801,13 @@ fn test_branch_and_merge(cx: &mut TestAppContext) {
|
|||
|
||||
// Create a remote replica of the base buffer.
|
||||
let base_replica = cx.new(|cx| {
|
||||
Buffer::from_proto(1, Capability::ReadWrite, base.read(cx).to_proto(cx), None).unwrap()
|
||||
Buffer::from_proto(
|
||||
ReplicaId::new(1),
|
||||
Capability::ReadWrite,
|
||||
base.read(cx).to_proto(cx),
|
||||
None,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
base.update(cx, |_buffer, cx| {
|
||||
cx.subscribe(&base_replica, |this, _, event, cx| {
|
||||
|
|
@ -3108,7 +3121,8 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
.background_executor()
|
||||
.block(base_buffer.read(cx).serialize_ops(None, cx));
|
||||
let mut buffer =
|
||||
Buffer::from_proto(i as ReplicaId, Capability::ReadWrite, state, None).unwrap();
|
||||
Buffer::from_proto(ReplicaId::new(i as u16), Capability::ReadWrite, state, None)
|
||||
.unwrap();
|
||||
buffer.apply_ops(
|
||||
ops.into_iter()
|
||||
.map(|op| proto::deserialize_operation(op).unwrap()),
|
||||
|
|
@ -3133,9 +3147,9 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
});
|
||||
|
||||
buffers.push(buffer);
|
||||
replica_ids.push(i as ReplicaId);
|
||||
network.lock().add_peer(i as ReplicaId);
|
||||
log::info!("Adding initial peer with replica id {}", i);
|
||||
replica_ids.push(ReplicaId::new(i as u16));
|
||||
network.lock().add_peer(ReplicaId::new(i as u16));
|
||||
log::info!("Adding initial peer with replica id {:?}", replica_ids[i]);
|
||||
}
|
||||
|
||||
log::info!("initial text: {:?}", base_text);
|
||||
|
|
@ -3155,14 +3169,14 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
buffer.start_transaction_at(now);
|
||||
buffer.randomly_edit(&mut rng, 5, cx);
|
||||
buffer.end_transaction_at(now, cx);
|
||||
log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
|
||||
log::info!("buffer {:?} text: {:?}", buffer.replica_id(), buffer.text());
|
||||
});
|
||||
mutation_count -= 1;
|
||||
}
|
||||
30..=39 if mutation_count != 0 => {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
if rng.random_bool(0.2) {
|
||||
log::info!("peer {} clearing active selections", replica_id);
|
||||
log::info!("peer {:?} clearing active selections", replica_id);
|
||||
active_selections.remove(&replica_id);
|
||||
buffer.remove_active_selections(cx);
|
||||
} else {
|
||||
|
|
@ -3179,7 +3193,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
}
|
||||
let selections: Arc<[Selection<Anchor>]> = selections.into();
|
||||
log::info!(
|
||||
"peer {} setting active selections: {:?}",
|
||||
"peer {:?} setting active selections: {:?}",
|
||||
replica_id,
|
||||
selections
|
||||
);
|
||||
|
|
@ -3189,7 +3203,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
});
|
||||
mutation_count -= 1;
|
||||
}
|
||||
40..=49 if mutation_count != 0 && replica_id == 0 => {
|
||||
40..=49 if mutation_count != 0 && replica_id == ReplicaId::REMOTE_SERVER => {
|
||||
let entry_count = rng.random_range(1..=5);
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
let diagnostics = DiagnosticSet::new(
|
||||
|
|
@ -3207,7 +3221,11 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
}),
|
||||
buffer,
|
||||
);
|
||||
log::info!("peer {} setting diagnostics: {:?}", replica_id, diagnostics);
|
||||
log::info!(
|
||||
"peer {:?} setting diagnostics: {:?}",
|
||||
replica_id,
|
||||
diagnostics
|
||||
);
|
||||
buffer.update_diagnostics(LanguageServerId(0), diagnostics, cx);
|
||||
});
|
||||
mutation_count -= 1;
|
||||
|
|
@ -3217,12 +3235,13 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
let old_buffer_ops = cx
|
||||
.background_executor()
|
||||
.block(buffer.read(cx).serialize_ops(None, cx));
|
||||
let new_replica_id = (0..=replica_ids.len() as ReplicaId)
|
||||
let new_replica_id = (0..=replica_ids.len() as u16)
|
||||
.map(ReplicaId::new)
|
||||
.filter(|replica_id| *replica_id != buffer.read(cx).replica_id())
|
||||
.choose(&mut rng)
|
||||
.unwrap();
|
||||
log::info!(
|
||||
"Adding new replica {} (replicating from {})",
|
||||
"Adding new replica {:?} (replicating from {:?})",
|
||||
new_replica_id,
|
||||
replica_id
|
||||
);
|
||||
|
|
@ -3241,7 +3260,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
cx,
|
||||
);
|
||||
log::info!(
|
||||
"New replica {} text: {:?}",
|
||||
"New replica {:?} text: {:?}",
|
||||
new_buffer.replica_id(),
|
||||
new_buffer.text()
|
||||
);
|
||||
|
|
@ -3264,7 +3283,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
}));
|
||||
network.lock().replicate(replica_id, new_replica_id);
|
||||
|
||||
if new_replica_id as usize == replica_ids.len() {
|
||||
if new_replica_id.as_u16() as usize == replica_ids.len() {
|
||||
replica_ids.push(new_replica_id);
|
||||
} else {
|
||||
let new_buffer = new_buffer.take().unwrap();
|
||||
|
|
@ -3276,7 +3295,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
.map(|op| proto::deserialize_operation(op).unwrap());
|
||||
if ops.len() > 0 {
|
||||
log::info!(
|
||||
"peer {} (version: {:?}) applying {} ops from the network. {:?}",
|
||||
"peer {:?} (version: {:?}) applying {} ops from the network. {:?}",
|
||||
new_replica_id,
|
||||
buffer.read(cx).version(),
|
||||
ops.len(),
|
||||
|
|
@ -3287,13 +3306,13 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
});
|
||||
}
|
||||
}
|
||||
buffers[new_replica_id as usize] = new_buffer;
|
||||
buffers[new_replica_id.as_u16() as usize] = new_buffer;
|
||||
}
|
||||
}
|
||||
60..=69 if mutation_count != 0 => {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.randomly_undo_redo(&mut rng, cx);
|
||||
log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
|
||||
log::info!("buffer {:?} text: {:?}", buffer.replica_id(), buffer.text());
|
||||
});
|
||||
mutation_count -= 1;
|
||||
}
|
||||
|
|
@ -3305,7 +3324,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
.map(|op| proto::deserialize_operation(op).unwrap());
|
||||
if ops.len() > 0 {
|
||||
log::info!(
|
||||
"peer {} (version: {:?}) applying {} ops from the network. {:?}",
|
||||
"peer {:?} (version: {:?}) applying {} ops from the network. {:?}",
|
||||
replica_id,
|
||||
buffer.read(cx).version(),
|
||||
ops.len(),
|
||||
|
|
@ -3335,13 +3354,13 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
assert_eq!(
|
||||
buffer.version(),
|
||||
first_buffer.version(),
|
||||
"Replica {} version != Replica 0 version",
|
||||
"Replica {:?} version != Replica 0 version",
|
||||
buffer.replica_id()
|
||||
);
|
||||
assert_eq!(
|
||||
buffer.text(),
|
||||
first_buffer.text(),
|
||||
"Replica {} text != Replica 0 text",
|
||||
"Replica {:?} text != Replica 0 text",
|
||||
buffer.replica_id()
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -3351,7 +3370,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
first_buffer
|
||||
.diagnostics_in_range::<_, usize>(0..first_buffer.len(), false)
|
||||
.collect::<Vec<_>>(),
|
||||
"Replica {} diagnostics != Replica 0 diagnostics",
|
||||
"Replica {:?} diagnostics != Replica 0 diagnostics",
|
||||
buffer.replica_id()
|
||||
);
|
||||
}
|
||||
|
|
@ -3370,7 +3389,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
assert_eq!(
|
||||
actual_remote_selections,
|
||||
expected_remote_selections,
|
||||
"Replica {} remote selections != expected selections",
|
||||
"Replica {:?} remote selections != expected selections",
|
||||
buffer.replica_id()
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
|||
|
||||
crate::Operation::Buffer(text::Operation::Undo(undo)) => {
|
||||
proto::operation::Variant::Undo(proto::operation::Undo {
|
||||
replica_id: undo.timestamp.replica_id as u32,
|
||||
replica_id: undo.timestamp.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: undo.timestamp.value,
|
||||
version: serialize_version(&undo.version),
|
||||
counts: undo
|
||||
.counts
|
||||
.iter()
|
||||
.map(|(edit_id, count)| proto::UndoCount {
|
||||
replica_id: edit_id.replica_id as u32,
|
||||
replica_id: edit_id.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: edit_id.value,
|
||||
count: *count,
|
||||
})
|
||||
|
|
@ -60,7 +60,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
|||
lamport_timestamp,
|
||||
cursor_shape,
|
||||
} => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
|
||||
replica_id: lamport_timestamp.replica_id as u32,
|
||||
replica_id: lamport_timestamp.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: lamport_timestamp.value,
|
||||
selections: serialize_selections(selections),
|
||||
line_mode: *line_mode,
|
||||
|
|
@ -72,7 +72,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
|||
server_id,
|
||||
diagnostics,
|
||||
} => proto::operation::Variant::UpdateDiagnostics(proto::UpdateDiagnostics {
|
||||
replica_id: lamport_timestamp.replica_id as u32,
|
||||
replica_id: lamport_timestamp.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: lamport_timestamp.value,
|
||||
server_id: server_id.0 as u64,
|
||||
diagnostics: serialize_diagnostics(diagnostics.iter()),
|
||||
|
|
@ -84,7 +84,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
|||
server_id,
|
||||
} => proto::operation::Variant::UpdateCompletionTriggers(
|
||||
proto::operation::UpdateCompletionTriggers {
|
||||
replica_id: lamport_timestamp.replica_id as u32,
|
||||
replica_id: lamport_timestamp.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: lamport_timestamp.value,
|
||||
triggers: triggers.clone(),
|
||||
language_server_id: server_id.to_proto(),
|
||||
|
|
@ -95,7 +95,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
|||
line_ending,
|
||||
lamport_timestamp,
|
||||
} => proto::operation::Variant::UpdateLineEnding(proto::operation::UpdateLineEnding {
|
||||
replica_id: lamport_timestamp.replica_id as u32,
|
||||
replica_id: lamport_timestamp.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: lamport_timestamp.value,
|
||||
line_ending: serialize_line_ending(*line_ending) as i32,
|
||||
}),
|
||||
|
|
@ -106,7 +106,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation {
|
|||
/// Serializes an [`EditOperation`] to be sent over RPC.
|
||||
pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit {
|
||||
proto::operation::Edit {
|
||||
replica_id: operation.timestamp.replica_id as u32,
|
||||
replica_id: operation.timestamp.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: operation.timestamp.value,
|
||||
version: serialize_version(&operation.version),
|
||||
ranges: operation.ranges.iter().map(serialize_range).collect(),
|
||||
|
|
@ -123,12 +123,12 @@ pub fn serialize_undo_map_entry(
|
|||
(edit_id, counts): (&clock::Lamport, &[(clock::Lamport, u32)]),
|
||||
) -> proto::UndoMapEntry {
|
||||
proto::UndoMapEntry {
|
||||
replica_id: edit_id.replica_id as u32,
|
||||
replica_id: edit_id.replica_id.as_u16() as u32,
|
||||
local_timestamp: edit_id.value,
|
||||
counts: counts
|
||||
.iter()
|
||||
.map(|(undo_id, count)| proto::UndoCount {
|
||||
replica_id: undo_id.replica_id as u32,
|
||||
replica_id: undo_id.replica_id.as_u16() as u32,
|
||||
lamport_timestamp: undo_id.value,
|
||||
count: *count,
|
||||
})
|
||||
|
|
@ -246,7 +246,7 @@ pub fn serialize_diagnostics<'a>(
|
|||
/// Serializes an [`Anchor`] to be sent over RPC.
|
||||
pub fn serialize_anchor(anchor: &Anchor) -> proto::Anchor {
|
||||
proto::Anchor {
|
||||
replica_id: anchor.timestamp.replica_id as u32,
|
||||
replica_id: anchor.timestamp.replica_id.as_u16() as u32,
|
||||
timestamp: anchor.timestamp.value,
|
||||
offset: anchor.offset as u64,
|
||||
bias: match anchor.bias {
|
||||
|
|
@ -283,7 +283,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
proto::operation::Variant::Undo(undo) => {
|
||||
crate::Operation::Buffer(text::Operation::Undo(UndoOperation {
|
||||
timestamp: clock::Lamport {
|
||||
replica_id: undo.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(undo.replica_id as u16),
|
||||
value: undo.lamport_timestamp,
|
||||
},
|
||||
version: deserialize_version(&undo.version),
|
||||
|
|
@ -293,7 +293,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
.map(|c| {
|
||||
(
|
||||
clock::Lamport {
|
||||
replica_id: c.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(c.replica_id as u16),
|
||||
value: c.lamport_timestamp,
|
||||
},
|
||||
c.count,
|
||||
|
|
@ -319,7 +319,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
|
||||
crate::Operation::UpdateSelections {
|
||||
lamport_timestamp: clock::Lamport {
|
||||
replica_id: message.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(message.replica_id as u16),
|
||||
value: message.lamport_timestamp,
|
||||
},
|
||||
selections: Arc::from(selections),
|
||||
|
|
@ -333,7 +333,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
proto::operation::Variant::UpdateDiagnostics(message) => {
|
||||
crate::Operation::UpdateDiagnostics {
|
||||
lamport_timestamp: clock::Lamport {
|
||||
replica_id: message.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(message.replica_id as u16),
|
||||
value: message.lamport_timestamp,
|
||||
},
|
||||
server_id: LanguageServerId(message.server_id as usize),
|
||||
|
|
@ -344,7 +344,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
crate::Operation::UpdateCompletionTriggers {
|
||||
triggers: message.triggers,
|
||||
lamport_timestamp: clock::Lamport {
|
||||
replica_id: message.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(message.replica_id as u16),
|
||||
value: message.lamport_timestamp,
|
||||
},
|
||||
server_id: LanguageServerId::from_proto(message.language_server_id),
|
||||
|
|
@ -353,7 +353,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
proto::operation::Variant::UpdateLineEnding(message) => {
|
||||
crate::Operation::UpdateLineEnding {
|
||||
lamport_timestamp: clock::Lamport {
|
||||
replica_id: message.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(message.replica_id as u16),
|
||||
value: message.lamport_timestamp,
|
||||
},
|
||||
line_ending: deserialize_line_ending(
|
||||
|
|
@ -370,7 +370,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
|
|||
pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation {
|
||||
EditOperation {
|
||||
timestamp: clock::Lamport {
|
||||
replica_id: edit.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(edit.replica_id as u16),
|
||||
value: edit.lamport_timestamp,
|
||||
},
|
||||
version: deserialize_version(&edit.version),
|
||||
|
|
@ -385,7 +385,7 @@ pub fn deserialize_undo_map_entry(
|
|||
) -> (clock::Lamport, Vec<(clock::Lamport, u32)>) {
|
||||
(
|
||||
clock::Lamport {
|
||||
replica_id: entry.replica_id as u16,
|
||||
replica_id: ReplicaId::new(entry.replica_id as u16),
|
||||
value: entry.local_timestamp,
|
||||
},
|
||||
entry
|
||||
|
|
@ -394,7 +394,7 @@ pub fn deserialize_undo_map_entry(
|
|||
.map(|undo_count| {
|
||||
(
|
||||
clock::Lamport {
|
||||
replica_id: undo_count.replica_id as u16,
|
||||
replica_id: ReplicaId::new(undo_count.replica_id as u16),
|
||||
value: undo_count.lamport_timestamp,
|
||||
},
|
||||
undo_count.count,
|
||||
|
|
@ -480,7 +480,7 @@ pub fn deserialize_anchor(anchor: proto::Anchor) -> Option<Anchor> {
|
|||
};
|
||||
Some(Anchor {
|
||||
timestamp: clock::Lamport {
|
||||
replica_id: anchor.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(anchor.replica_id as u16),
|
||||
value: anchor.timestamp,
|
||||
},
|
||||
offset: anchor.offset as usize,
|
||||
|
|
@ -524,7 +524,7 @@ pub fn lamport_timestamp_for_operation(operation: &proto::Operation) -> Option<c
|
|||
}
|
||||
|
||||
Some(clock::Lamport {
|
||||
replica_id: replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(replica_id as u16),
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
|
@ -559,7 +559,7 @@ pub fn deserialize_transaction(transaction: proto::Transaction) -> Result<Transa
|
|||
/// Serializes a [`clock::Lamport`] timestamp to be sent over RPC.
|
||||
pub fn serialize_timestamp(timestamp: clock::Lamport) -> proto::LamportTimestamp {
|
||||
proto::LamportTimestamp {
|
||||
replica_id: timestamp.replica_id as u32,
|
||||
replica_id: timestamp.replica_id.as_u16() as u32,
|
||||
value: timestamp.value,
|
||||
}
|
||||
}
|
||||
|
|
@ -567,7 +567,7 @@ pub fn serialize_timestamp(timestamp: clock::Lamport) -> proto::LamportTimestamp
|
|||
/// Deserializes a [`clock::Lamport`] timestamp from the RPC representation.
|
||||
pub fn deserialize_timestamp(timestamp: proto::LamportTimestamp) -> clock::Lamport {
|
||||
clock::Lamport {
|
||||
replica_id: timestamp.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(timestamp.replica_id as u16),
|
||||
value: timestamp.value,
|
||||
}
|
||||
}
|
||||
|
|
@ -590,7 +590,7 @@ pub fn deserialize_version(message: &[proto::VectorClockEntry]) -> clock::Global
|
|||
let mut version = clock::Global::new();
|
||||
for entry in message {
|
||||
version.observe(clock::Lamport {
|
||||
replica_id: entry.replica_id as ReplicaId,
|
||||
replica_id: ReplicaId::new(entry.replica_id as u16),
|
||||
value: entry.timestamp,
|
||||
});
|
||||
}
|
||||
|
|
@ -602,7 +602,7 @@ pub fn serialize_version(version: &clock::Global) -> Vec<proto::VectorClockEntry
|
|||
version
|
||||
.iter()
|
||||
.map(|entry| proto::VectorClockEntry {
|
||||
replica_id: entry.replica_id as u32,
|
||||
replica_id: entry.replica_id.as_u16() as u32,
|
||||
timestamp: entry.value,
|
||||
})
|
||||
.collect()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
use gpui::App;
|
||||
use rand::rngs::StdRng;
|
||||
use std::{env, ops::Range, sync::Arc};
|
||||
use text::{Buffer, BufferId};
|
||||
use text::{Buffer, BufferId, ReplicaId};
|
||||
use tree_sitter::Node;
|
||||
use unindent::Unindent as _;
|
||||
use util::test::marked_text_ranges;
|
||||
|
|
@ -88,7 +88,7 @@ fn test_syntax_map_layers_for_range(cx: &mut App) {
|
|||
registry.add(language.clone());
|
||||
|
||||
let mut buffer = Buffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
r#"
|
||||
fn a() {
|
||||
|
|
@ -189,7 +189,7 @@ fn test_dynamic_language_injection(cx: &mut App) {
|
|||
registry.add(Arc::new(ruby_lang()));
|
||||
|
||||
let mut buffer = Buffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
r#"
|
||||
This is a code block:
|
||||
|
|
@ -811,7 +811,7 @@ fn test_syntax_map_languages_loading_with_erb(cx: &mut App) {
|
|||
.unindent();
|
||||
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), text);
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), text);
|
||||
|
||||
let mut syntax_map = SyntaxMap::new(&buffer);
|
||||
syntax_map.set_language_registry(registry.clone());
|
||||
|
|
@ -978,7 +978,7 @@ fn test_random_edits(
|
|||
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
|
||||
.unwrap_or(10);
|
||||
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), text);
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), text);
|
||||
|
||||
let mut syntax_map = SyntaxMap::new(&buffer);
|
||||
syntax_map.set_language_registry(registry.clone());
|
||||
|
|
@ -1159,7 +1159,7 @@ fn test_edit_sequence(language_name: &str, steps: &[&str], cx: &mut App) -> (Buf
|
|||
.now_or_never()
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "");
|
||||
|
||||
let mut mutated_syntax_map = SyntaxMap::new(&buffer);
|
||||
mutated_syntax_map.set_language_registry(registry.clone());
|
||||
|
|
|
|||
|
|
@ -666,7 +666,7 @@ impl MultiBuffer {
|
|||
paths_by_excerpt: Default::default(),
|
||||
buffer_changed_since_sync: Default::default(),
|
||||
history: History {
|
||||
next_transaction_id: clock::Lamport::default(),
|
||||
next_transaction_id: clock::Lamport::MIN,
|
||||
undo_stack: Vec::new(),
|
||||
redo_stack: Vec::new(),
|
||||
transaction_depth: 0,
|
||||
|
|
|
|||
|
|
@ -78,7 +78,9 @@ fn test_remote(cx: &mut App) {
|
|||
let ops = cx
|
||||
.background_executor()
|
||||
.block(host_buffer.read(cx).serialize_ops(None, cx));
|
||||
let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
|
||||
let mut buffer =
|
||||
Buffer::from_proto(ReplicaId::REMOTE_SERVER, Capability::ReadWrite, state, None)
|
||||
.unwrap();
|
||||
buffer.apply_ops(
|
||||
ops.into_iter()
|
||||
.map(|op| language::proto::deserialize_operation(op).unwrap()),
|
||||
|
|
@ -3636,7 +3638,7 @@ fn assert_position_translation(snapshot: &MultiBufferSnapshot) {
|
|||
fn assert_line_indents(snapshot: &MultiBufferSnapshot) {
|
||||
let max_row = snapshot.max_point().row;
|
||||
let buffer_id = snapshot.excerpts().next().unwrap().1.remote_id();
|
||||
let text = text::Buffer::new(0, buffer_id, snapshot.text());
|
||||
let text = text::Buffer::new(ReplicaId::LOCAL, buffer_id, snapshot.text());
|
||||
let mut line_indents = text
|
||||
.line_indents_in_row_range(0..max_row + 1)
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use rpc::{
|
|||
};
|
||||
use smol::channel::Receiver;
|
||||
use std::{io, pin::pin, sync::Arc, time::Instant};
|
||||
use text::BufferId;
|
||||
use text::{BufferId, ReplicaId};
|
||||
use util::{ResultExt as _, TryFutureExt, debug_panic, maybe, rel_path::RelPath};
|
||||
use worktree::{File, PathChange, ProjectEntryId, Worktree, WorktreeId};
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ impl RemoteBufferStore {
|
|||
pub fn handle_create_buffer_for_peer(
|
||||
&mut self,
|
||||
envelope: TypedEnvelope<proto::CreateBufferForPeer>,
|
||||
replica_id: u16,
|
||||
replica_id: ReplicaId,
|
||||
capability: Capability,
|
||||
cx: &mut Context<BufferStore>,
|
||||
) -> Result<Option<Entity<Buffer>>> {
|
||||
|
|
@ -626,7 +626,9 @@ impl LocalBufferStore {
|
|||
cx.spawn(async move |_, cx| {
|
||||
let loaded = load_file.await?;
|
||||
let text_buffer = cx
|
||||
.background_spawn(async move { text::Buffer::new(0, buffer_id, loaded.text) })
|
||||
.background_spawn(async move {
|
||||
text::Buffer::new(ReplicaId::LOCAL, buffer_id, loaded.text)
|
||||
})
|
||||
.await;
|
||||
cx.insert_entity(reservation, |_| {
|
||||
Buffer::build(text_buffer, Some(loaded.file), Capability::ReadWrite)
|
||||
|
|
@ -639,7 +641,7 @@ impl LocalBufferStore {
|
|||
Ok(buffer) => Ok(buffer),
|
||||
Err(error) if is_not_found_error(&error) => cx.new(|cx| {
|
||||
let buffer_id = BufferId::from(cx.entity_id().as_non_zero_u64());
|
||||
let text_buffer = text::Buffer::new(0, buffer_id, "");
|
||||
let text_buffer = text::Buffer::new(ReplicaId::LOCAL, buffer_id, "");
|
||||
Buffer::build(
|
||||
text_buffer,
|
||||
Some(Arc::new(File {
|
||||
|
|
@ -917,7 +919,7 @@ impl BufferStore {
|
|||
path: file.path.clone(),
|
||||
worktree_id: file.worktree_id(cx),
|
||||
});
|
||||
let is_remote = buffer.replica_id() != 0;
|
||||
let is_remote = buffer.replica_id().is_remote();
|
||||
let open_buffer = OpenBuffer::Complete {
|
||||
buffer: buffer_entity.downgrade(),
|
||||
};
|
||||
|
|
@ -1317,7 +1319,7 @@ impl BufferStore {
|
|||
pub fn handle_create_buffer_for_peer(
|
||||
&mut self,
|
||||
envelope: TypedEnvelope<proto::CreateBufferForPeer>,
|
||||
replica_id: u16,
|
||||
replica_id: ReplicaId,
|
||||
capability: Capability,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ mod tests {
|
|||
use language::language_settings::AllLanguageSettings;
|
||||
use serde_json::json;
|
||||
use settings::Settings as _;
|
||||
use text::{Buffer, BufferId, Point, ToOffset as _};
|
||||
use text::{Buffer, BufferId, Point, ReplicaId, ToOffset as _};
|
||||
use unindent::Unindent as _;
|
||||
use util::{path, rel_path::rel_path};
|
||||
use worktree::WorktreeSettings;
|
||||
|
|
@ -299,7 +299,7 @@ mod tests {
|
|||
.unindent();
|
||||
|
||||
let buffer_id = BufferId::new(1).unwrap();
|
||||
let buffer = Buffer::new(0, buffer_id, test_content);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, buffer_id, test_content);
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let conflict_snapshot = ConflictSet::parse(&snapshot);
|
||||
|
|
@ -374,7 +374,7 @@ mod tests {
|
|||
.unindent();
|
||||
|
||||
let buffer_id = BufferId::new(1).unwrap();
|
||||
let buffer = Buffer::new(0, buffer_id, test_content);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, buffer_id, test_content);
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let conflict_snapshot = ConflictSet::parse(&snapshot);
|
||||
|
|
@ -405,7 +405,7 @@ mod tests {
|
|||
>>>>>>> "#
|
||||
.unindent();
|
||||
let buffer_id = BufferId::new(1).unwrap();
|
||||
let buffer = Buffer::new(0, buffer_id, test_content);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, buffer_id, test_content);
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let conflict_snapshot = ConflictSet::parse(&snapshot);
|
||||
|
|
@ -447,7 +447,7 @@ mod tests {
|
|||
.unindent();
|
||||
|
||||
let buffer_id = BufferId::new(1).unwrap();
|
||||
let buffer = Buffer::new(0, buffer_id, test_content.clone());
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, buffer_id, test_content.clone());
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let conflict_snapshot = ConflictSet::parse(&snapshot);
|
||||
|
|
|
|||
|
|
@ -3025,9 +3025,8 @@ impl LocalLspStore {
|
|||
Some(buffer_to_edit.read(cx).saved_version().clone())
|
||||
};
|
||||
|
||||
let most_recent_edit = version.and_then(|version| {
|
||||
version.iter().max_by_key(|timestamp| timestamp.value)
|
||||
});
|
||||
let most_recent_edit =
|
||||
version.and_then(|version| version.most_recent());
|
||||
// Check if the edit that triggered that edit has been made by this participant.
|
||||
|
||||
if let Some(most_recent_edit) = most_recent_edit {
|
||||
|
|
|
|||
|
|
@ -1560,7 +1560,7 @@ impl Project {
|
|||
})?;
|
||||
|
||||
let agent_server_store = cx.new(|cx| AgentServerStore::collab(cx))?;
|
||||
let replica_id = response.payload.replica_id as ReplicaId;
|
||||
let replica_id = ReplicaId::new(response.payload.replica_id as u16);
|
||||
|
||||
let project = cx.new(|cx| {
|
||||
let snippets = SnippetProvider::new(fs.clone(), BTreeSet::from_iter([]), cx);
|
||||
|
|
@ -1975,9 +1975,9 @@ impl Project {
|
|||
ProjectClientState::Remote { replica_id, .. } => replica_id,
|
||||
_ => {
|
||||
if self.remote_client.is_some() {
|
||||
1
|
||||
ReplicaId::REMOTE_SERVER
|
||||
} else {
|
||||
0
|
||||
ReplicaId::LOCAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4307,7 +4307,7 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
|
|||
let remote = cx.update(|cx| {
|
||||
Worktree::remote(
|
||||
0,
|
||||
1,
|
||||
ReplicaId::REMOTE_SERVER,
|
||||
metadata,
|
||||
project.read(cx).client().into(),
|
||||
project.read(cx).path_style(cx),
|
||||
|
|
|
|||
|
|
@ -551,7 +551,7 @@ impl WorktreeStore {
|
|||
let worktree = cx.update(|cx| {
|
||||
Worktree::remote(
|
||||
REMOTE_SERVER_PROJECT_ID,
|
||||
0,
|
||||
ReplicaId::REMOTE_SERVER,
|
||||
proto::WorktreeMetadata {
|
||||
id: response.worktree_id,
|
||||
root_name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::{cmp::Ordering, fmt::Debug, ops::Range};
|
|||
use sum_tree::{Bias, Dimensions};
|
||||
|
||||
/// A timestamped position in a buffer
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Default)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
||||
pub struct Anchor {
|
||||
pub timestamp: clock::Lamport,
|
||||
/// The byte offset in the buffer
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use clock::Lamport;
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
use sum_tree::{ContextLessSummary, Dimension, Edit, Item, KeyedItem, SumTree};
|
||||
|
||||
|
|
@ -11,10 +12,10 @@ struct OperationItem<T>(T);
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct OperationQueue<T: Operation>(SumTree<OperationItem<T>>);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct OperationKey(clock::Lamport);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct OperationSummary {
|
||||
pub key: OperationKey,
|
||||
pub len: usize,
|
||||
|
|
@ -69,7 +70,10 @@ impl<T: Operation> OperationQueue<T> {
|
|||
|
||||
impl ContextLessSummary for OperationSummary {
|
||||
fn zero() -> Self {
|
||||
Default::default()
|
||||
OperationSummary {
|
||||
key: OperationKey::new(Lamport::MIN),
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, other: &Self) {
|
||||
|
|
@ -93,7 +97,7 @@ impl Add<&Self> for OperationSummary {
|
|||
|
||||
impl Dimension<'_, OperationSummary> for OperationKey {
|
||||
fn zero(_cx: ()) -> Self {
|
||||
Default::default()
|
||||
OperationKey::new(Lamport::MIN)
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &OperationSummary, _: ()) {
|
||||
|
|
@ -123,11 +127,13 @@ impl<T: Operation> KeyedItem for OperationItem<T> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use clock::ReplicaId;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_len() {
|
||||
let mut clock = clock::Lamport::new(0);
|
||||
let mut clock = clock::Lamport::new(ReplicaId::LOCAL);
|
||||
|
||||
let mut queue = OperationQueue::new();
|
||||
assert_eq!(queue.len(), 0);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ fn init_logger() {
|
|||
|
||||
#[test]
|
||||
fn test_edit() {
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "abc");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "abc");
|
||||
assert_eq!(buffer.text(), "abc");
|
||||
buffer.edit([(3..3, "def")]);
|
||||
assert_eq!(buffer.text(), "abcdef");
|
||||
|
|
@ -40,7 +40,11 @@ fn test_random_edits(mut rng: StdRng) {
|
|||
let mut reference_string = RandomCharIter::new(&mut rng)
|
||||
.take(reference_string_len)
|
||||
.collect::<String>();
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), reference_string.clone());
|
||||
let mut buffer = Buffer::new(
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
reference_string.clone(),
|
||||
);
|
||||
LineEnding::normalize(&mut reference_string);
|
||||
|
||||
buffer.set_group_interval(Duration::from_millis(rng.random_range(0..=200)));
|
||||
|
|
@ -176,7 +180,11 @@ fn test_line_endings() {
|
|||
LineEnding::Windows
|
||||
);
|
||||
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "one\r\ntwo\rthree");
|
||||
let mut buffer = Buffer::new(
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
"one\r\ntwo\rthree",
|
||||
);
|
||||
assert_eq!(buffer.text(), "one\ntwo\nthree");
|
||||
assert_eq!(buffer.line_ending(), LineEnding::Windows);
|
||||
buffer.check_invariants();
|
||||
|
|
@ -190,7 +198,7 @@ fn test_line_endings() {
|
|||
|
||||
#[test]
|
||||
fn test_line_len() {
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "");
|
||||
buffer.edit([(0..0, "abcd\nefg\nhij")]);
|
||||
buffer.edit([(12..12, "kl\nmno")]);
|
||||
buffer.edit([(18..18, "\npqrs\n")]);
|
||||
|
|
@ -207,7 +215,7 @@ fn test_line_len() {
|
|||
#[test]
|
||||
fn test_common_prefix_at_position() {
|
||||
let text = "a = str; b = δα";
|
||||
let buffer = Buffer::new(0, BufferId::new(1).unwrap(), text);
|
||||
let buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), text);
|
||||
|
||||
let offset1 = offset_after(text, "str");
|
||||
let offset2 = offset_after(text, "δα");
|
||||
|
|
@ -256,7 +264,7 @@ fn test_common_prefix_at_position() {
|
|||
#[test]
|
||||
fn test_text_summary_for_range() {
|
||||
let buffer = Buffer::new(
|
||||
0,
|
||||
ReplicaId::LOCAL,
|
||||
BufferId::new(1).unwrap(),
|
||||
"ab\nefg\nhklm\nnopqrs\ntuvwxyz",
|
||||
);
|
||||
|
|
@ -348,7 +356,7 @@ fn test_text_summary_for_range() {
|
|||
|
||||
#[test]
|
||||
fn test_chars_at() {
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "");
|
||||
buffer.edit([(0..0, "abcd\nefgh\nij")]);
|
||||
buffer.edit([(12..12, "kl\nmno")]);
|
||||
buffer.edit([(18..18, "\npqrs")]);
|
||||
|
|
@ -370,7 +378,7 @@ fn test_chars_at() {
|
|||
assert_eq!(chars.collect::<String>(), "PQrs");
|
||||
|
||||
// Regression test:
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "");
|
||||
buffer.edit([(0..0, "[workspace]\nmembers = [\n \"xray_core\",\n \"xray_server\",\n \"xray_cli\",\n \"xray_wasm\",\n]\n")]);
|
||||
buffer.edit([(60..60, "\n")]);
|
||||
|
||||
|
|
@ -380,7 +388,7 @@ fn test_chars_at() {
|
|||
|
||||
#[test]
|
||||
fn test_anchors() {
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "");
|
||||
buffer.edit([(0..0, "abc")]);
|
||||
let left_anchor = buffer.anchor_before(2);
|
||||
let right_anchor = buffer.anchor_after(2);
|
||||
|
|
@ -498,7 +506,7 @@ fn test_anchors() {
|
|||
|
||||
#[test]
|
||||
fn test_anchors_at_start_and_end() {
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "");
|
||||
let before_start_anchor = buffer.anchor_before(0);
|
||||
let after_end_anchor = buffer.anchor_after(0);
|
||||
|
||||
|
|
@ -521,7 +529,7 @@ fn test_anchors_at_start_and_end() {
|
|||
|
||||
#[test]
|
||||
fn test_undo_redo() {
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "1234");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "1234");
|
||||
// Set group interval to zero so as to not group edits in the undo stack.
|
||||
buffer.set_group_interval(Duration::from_secs(0));
|
||||
|
||||
|
|
@ -558,7 +566,7 @@ fn test_undo_redo() {
|
|||
#[test]
|
||||
fn test_history() {
|
||||
let mut now = Instant::now();
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "123456");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "123456");
|
||||
buffer.set_group_interval(Duration::from_millis(300));
|
||||
|
||||
let transaction_1 = buffer.start_transaction_at(now).unwrap();
|
||||
|
|
@ -625,7 +633,7 @@ fn test_history() {
|
|||
#[test]
|
||||
fn test_finalize_last_transaction() {
|
||||
let now = Instant::now();
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "123456");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "123456");
|
||||
buffer.history.group_interval = Duration::from_millis(1);
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
|
|
@ -661,7 +669,7 @@ fn test_finalize_last_transaction() {
|
|||
#[test]
|
||||
fn test_edited_ranges_for_transaction() {
|
||||
let now = Instant::now();
|
||||
let mut buffer = Buffer::new(0, BufferId::new(1).unwrap(), "1234567");
|
||||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), "1234567");
|
||||
|
||||
buffer.start_transaction_at(now);
|
||||
buffer.edit([(2..4, "cd")]);
|
||||
|
|
@ -700,9 +708,9 @@ fn test_edited_ranges_for_transaction() {
|
|||
fn test_concurrent_edits() {
|
||||
let text = "abcdef";
|
||||
|
||||
let mut buffer1 = Buffer::new(1, BufferId::new(1).unwrap(), text);
|
||||
let mut buffer2 = Buffer::new(2, BufferId::new(1).unwrap(), text);
|
||||
let mut buffer3 = Buffer::new(3, BufferId::new(1).unwrap(), text);
|
||||
let mut buffer1 = Buffer::new(ReplicaId::new(1), BufferId::new(1).unwrap(), text);
|
||||
let mut buffer2 = Buffer::new(ReplicaId::new(2), BufferId::new(1).unwrap(), text);
|
||||
let mut buffer3 = Buffer::new(ReplicaId::new(3), BufferId::new(1).unwrap(), text);
|
||||
|
||||
let buf1_op = buffer1.edit([(1..2, "12")]);
|
||||
assert_eq!(buffer1.text(), "a12cdef");
|
||||
|
|
@ -741,11 +749,15 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
|
|||
let mut network = Network::new(rng.clone());
|
||||
|
||||
for i in 0..peers {
|
||||
let mut buffer = Buffer::new(i as ReplicaId, BufferId::new(1).unwrap(), base_text.clone());
|
||||
let mut buffer = Buffer::new(
|
||||
ReplicaId::new(i as u16),
|
||||
BufferId::new(1).unwrap(),
|
||||
base_text.clone(),
|
||||
);
|
||||
buffer.history.group_interval = Duration::from_millis(rng.random_range(0..=200));
|
||||
buffers.push(buffer);
|
||||
replica_ids.push(i as u16);
|
||||
network.add_peer(i as u16);
|
||||
replica_ids.push(ReplicaId::new(i as u16));
|
||||
network.add_peer(ReplicaId::new(i as u16));
|
||||
}
|
||||
|
||||
log::info!("initial text: {:?}", base_text);
|
||||
|
|
@ -759,7 +771,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
|
|||
0..=50 if mutation_count != 0 => {
|
||||
let op = buffer.randomly_edit(&mut rng, 5).1;
|
||||
network.broadcast(buffer.replica_id, vec![op]);
|
||||
log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
|
||||
log::info!("buffer {:?} text: {:?}", buffer.replica_id, buffer.text());
|
||||
mutation_count -= 1;
|
||||
}
|
||||
51..=70 if mutation_count != 0 => {
|
||||
|
|
@ -771,7 +783,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
|
|||
let ops = network.receive(replica_id);
|
||||
if !ops.is_empty() {
|
||||
log::info!(
|
||||
"peer {} applying {} ops from the network.",
|
||||
"peer {:?} applying {} ops from the network.",
|
||||
replica_id,
|
||||
ops.len()
|
||||
);
|
||||
|
|
@ -792,7 +804,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
|
|||
assert_eq!(
|
||||
buffer.text(),
|
||||
first_buffer.text(),
|
||||
"Replica {} text != Replica 0 text",
|
||||
"Replica {:?} text != Replica 0 text",
|
||||
buffer.replica_id
|
||||
);
|
||||
buffer.check_invariants();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ mod undo_map;
|
|||
|
||||
pub use anchor::*;
|
||||
use anyhow::{Context as _, Result};
|
||||
use clock::LOCAL_BRANCH_REPLICA_ID;
|
||||
use clock::Lamport;
|
||||
pub use clock::ReplicaId;
|
||||
use collections::{HashMap, HashSet};
|
||||
use locator::Locator;
|
||||
|
|
@ -573,7 +573,7 @@ struct InsertionFragment {
|
|||
fragment_id: Locator,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct InsertionFragmentKey {
|
||||
timestamp: clock::Lamport,
|
||||
split_offset: usize,
|
||||
|
|
@ -709,7 +709,7 @@ impl FromIterator<char> for LineIndent {
|
|||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn new(replica_id: u16, remote_id: BufferId, base_text: impl Into<String>) -> Buffer {
|
||||
pub fn new(replica_id: ReplicaId, remote_id: BufferId, base_text: impl Into<String>) -> Buffer {
|
||||
let mut base_text = base_text.into();
|
||||
let line_ending = LineEnding::detect(&base_text);
|
||||
LineEnding::normalize(&mut base_text);
|
||||
|
|
@ -717,7 +717,7 @@ impl Buffer {
|
|||
}
|
||||
|
||||
pub fn new_normalized(
|
||||
replica_id: u16,
|
||||
replica_id: ReplicaId,
|
||||
remote_id: BufferId,
|
||||
line_ending: LineEnding,
|
||||
normalized: Rope,
|
||||
|
|
@ -731,10 +731,7 @@ impl Buffer {
|
|||
|
||||
let visible_text = history.base_text.clone();
|
||||
if !visible_text.is_empty() {
|
||||
let insertion_timestamp = clock::Lamport {
|
||||
replica_id: 0,
|
||||
value: 1,
|
||||
};
|
||||
let insertion_timestamp = clock::Lamport::new(ReplicaId::LOCAL);
|
||||
lamport_clock.observe(insertion_timestamp);
|
||||
version.observe(insertion_timestamp);
|
||||
let fragment_id = Locator::between(&Locator::min(), &Locator::max());
|
||||
|
|
@ -788,7 +785,7 @@ impl Buffer {
|
|||
history: History::new(self.base_text().clone()),
|
||||
deferred_ops: OperationQueue::new(),
|
||||
deferred_replicas: HashSet::default(),
|
||||
lamport_clock: clock::Lamport::new(LOCAL_BRANCH_REPLICA_ID),
|
||||
lamport_clock: clock::Lamport::new(ReplicaId::LOCAL_BRANCH),
|
||||
subscriptions: Default::default(),
|
||||
edit_id_resolvers: Default::default(),
|
||||
wait_for_version_txs: Default::default(),
|
||||
|
|
@ -1254,7 +1251,7 @@ impl Buffer {
|
|||
for edit_id in edit_ids {
|
||||
let insertion_slice = InsertionSlice {
|
||||
edit_id: *edit_id,
|
||||
insertion_id: clock::Lamport::default(),
|
||||
insertion_id: clock::Lamport::MIN,
|
||||
range: 0..0,
|
||||
};
|
||||
let slices = self
|
||||
|
|
@ -1858,7 +1855,7 @@ impl Buffer {
|
|||
T: rand::Rng,
|
||||
{
|
||||
let mut edits = self.get_random_edits(rng, edit_count);
|
||||
log::info!("mutating buffer {} with {:?}", self.replica_id, edits);
|
||||
log::info!("mutating buffer {:?} with {:?}", self.replica_id, edits);
|
||||
|
||||
let op = self.edit(edits.iter().cloned());
|
||||
if let Operation::Edit(edit) = &op {
|
||||
|
|
@ -1881,7 +1878,7 @@ impl Buffer {
|
|||
if let Some(entry) = self.history.undo_stack.choose(rng) {
|
||||
let transaction = entry.transaction.clone();
|
||||
log::info!(
|
||||
"undoing buffer {} transaction {:?}",
|
||||
"undoing buffer {:?} transaction {:?}",
|
||||
self.replica_id,
|
||||
transaction
|
||||
);
|
||||
|
|
@ -2918,7 +2915,10 @@ impl InsertionFragment {
|
|||
|
||||
impl sum_tree::ContextLessSummary for InsertionFragmentKey {
|
||||
fn zero() -> Self {
|
||||
Default::default()
|
||||
InsertionFragmentKey {
|
||||
timestamp: Lamport::MIN,
|
||||
split_offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &Self) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::UndoOperation;
|
||||
use clock::Lamport;
|
||||
use std::cmp;
|
||||
use sum_tree::{Bias, SumTree};
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ impl sum_tree::KeyedItem for UndoMapEntry {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct UndoMapKey {
|
||||
edit_id: clock::Lamport,
|
||||
undo_id: clock::Lamport,
|
||||
|
|
@ -32,7 +33,10 @@ struct UndoMapKey {
|
|||
|
||||
impl sum_tree::ContextLessSummary for UndoMapKey {
|
||||
fn zero() -> Self {
|
||||
Default::default()
|
||||
UndoMapKey {
|
||||
edit_id: Lamport::MIN,
|
||||
undo_id: Lamport::MIN,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &Self) {
|
||||
|
|
@ -69,7 +73,7 @@ impl UndoMap {
|
|||
cursor.seek(
|
||||
&UndoMapKey {
|
||||
edit_id,
|
||||
undo_id: Default::default(),
|
||||
undo_id: Lamport::MIN,
|
||||
},
|
||||
Bias::Left,
|
||||
);
|
||||
|
|
@ -93,7 +97,7 @@ impl UndoMap {
|
|||
cursor.seek(
|
||||
&UndoMapKey {
|
||||
edit_id,
|
||||
undo_id: Default::default(),
|
||||
undo_id: Lamport::MIN,
|
||||
},
|
||||
Bias::Left,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -656,7 +656,7 @@ impl Worktree {
|
|||
|
||||
pub fn replica_id(&self) -> ReplicaId {
|
||||
match self {
|
||||
Worktree::Local(_) => 0,
|
||||
Worktree::Local(_) => ReplicaId::LOCAL,
|
||||
Worktree::Remote(worktree) => worktree.replica_id,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1581,7 +1581,7 @@ fn guess_token_count(bytes: usize) -> usize {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use client::test::FakeServer;
|
||||
use clock::FakeSystemClock;
|
||||
use clock::{FakeSystemClock, ReplicaId};
|
||||
use cloud_api_types::{CreateLlmTokenResponse, LlmToken};
|
||||
use gpui::TestAppContext;
|
||||
use http_client::FakeHttpClient;
|
||||
|
|
@ -1839,7 +1839,7 @@ mod tests {
|
|||
let buffer = cx.new(|_cx| {
|
||||
Buffer::remote(
|
||||
language::BufferId::new(1).unwrap(),
|
||||
1,
|
||||
ReplicaId::new(1),
|
||||
language::Capability::ReadWrite,
|
||||
"fn main() {\n println!(\"Hello\");\n}",
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue