Skip to content

Commit fed4666

Browse files
committed
refactor: generalize more of breakpoint logic for db/rr; TODO: more
moved setBreakpoints logic to handler; implemented some of the methods and placeholders for the others
1 parent 5753772 commit fed4666

File tree

7 files changed

+180
-124
lines changed

7 files changed

+180
-124
lines changed

src/db-backend/src/dap_server.rs

Lines changed: 5 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use crate::dap::{self, Capabilities, DapMessage, Event, ProtocolMessage, Response};
2-
use crate::dap_types::{self, Breakpoint, SetBreakpointsArguments, SetBreakpointsResponseBody, Source};
2+
use crate::dap_types;
33

44
use crate::db::Db;
55
use crate::handler::{Handler, TraceKind};
66
use crate::paths::CODETRACER_PATHS;
77
use crate::rr_dispatcher::CtRRArgs;
88
use crate::task::{
9-
gen_task_id, Action, CallSearchArg, CalltraceLoadArgs, CollapseCallsArgs, CtLoadFlowArguments,
9+
Action, CallSearchArg, CalltraceLoadArgs, CollapseCallsArgs, CtLoadFlowArguments,
1010
CtLoadLocalsArguments, FunctionLocation, LoadHistoryArg, LocalStepJump, Location, ProgramEvent, RunTracepointsArg,
11-
SourceCallJumpTarget, SourceLocation, StepArg, Task, TaskKind, TracepointId, UpdateTableArgs,
11+
SourceCallJumpTarget, SourceLocation, StepArg, TracepointId, UpdateTableArgs,
1212
};
1313

1414
use crate::trace_processor::{load_trace_data, load_trace_metadata, TraceProcessor};
@@ -20,7 +20,7 @@ use crate::transport::{DapResult, WorkerTransport};
2020

2121
use log::{info, warn};
2222
use serde_json::json;
23-
use std::collections::{HashMap, HashSet};
23+
// use std::collections::{HashMap, HashSet};
2424
use std::error::Error;
2525
use std::fmt;
2626

@@ -200,6 +200,7 @@ fn handle_request<T: DapTransport>(
200200
"stackTrace" => handler.stack_trace(req.clone(), req.load_args::<dap_types::StackTraceArguments>()?)?,
201201
"variables" => handler.variables(req.clone(), req.load_args::<dap_types::VariablesArguments>()?)?,
202202
"restart" => handler.run_to_entry(req.clone())?,
203+
"setBreakpoints" => handler.set_breakpoints(req.clone(), req.load_args::<dap_types::SetBreakpointsArguments>()?)?,
203204
"ct/load-locals" => handler.load_locals(req.clone(), req.load_args::<CtLoadLocalsArguments>()?)?,
204205
"ct/update-table" => handler.update_table(req.clone(), req.load_args::<UpdateTableArgs>()?)?,
205206
"ct/event-load" => handler.event_load(req.clone())?,
@@ -250,7 +251,6 @@ fn handle_request<T: DapTransport>(
250251

251252
pub struct Ctx {
252253
pub seq: i64,
253-
pub breakpoints: HashMap<String, HashSet<i64>>,
254254
pub handler: Option<Handler>,
255255
pub received_launch: bool,
256256
pub launch_trace_folder: PathBuf,
@@ -264,7 +264,6 @@ impl Default for Ctx {
264264
fn default() -> Self {
265265
Self {
266266
seq: 1i64,
267-
breakpoints: HashMap::new(),
268267
handler: None,
269268
received_launch: false,
270269
launch_trace_folder: PathBuf::from(""),
@@ -322,92 +321,6 @@ pub fn handle_message<T: DapTransport>(
322321
ctx.seq += 1;
323322
transport.send(&event)?;
324323
}
325-
DapMessage::Request(req) if req.command == "setBreakpoints" => {
326-
let mut results = Vec::new();
327-
let args = req.load_args::<SetBreakpointsArguments>()?;
328-
if let Some(path) = args.source.path.clone() {
329-
let lines: Vec<i64> = if let Some(bps) = args.breakpoints {
330-
bps.into_iter().map(|b| b.line).collect()
331-
} else {
332-
args.lines.unwrap_or_default()
333-
};
334-
let entry = ctx.breakpoints.entry(path.clone()).or_default();
335-
if let Some(h) = ctx.handler.as_mut() {
336-
h.clear_breakpoints();
337-
for line in lines {
338-
entry.insert(line);
339-
let _ = h.add_breakpoint(
340-
SourceLocation {
341-
path: path.clone(),
342-
line: line as usize,
343-
},
344-
Task {
345-
kind: TaskKind::AddBreak,
346-
id: gen_task_id(TaskKind::AddBreak),
347-
},
348-
);
349-
results.push(Breakpoint {
350-
id: None,
351-
verified: true,
352-
message: None,
353-
source: Some(Source {
354-
name: args.source.name.clone(),
355-
path: Some(path.clone()),
356-
source_reference: args.source.source_reference,
357-
presentation_hint: None,
358-
origin: None,
359-
sources: None,
360-
adapter_data: None,
361-
checksums: None,
362-
}),
363-
line: Some(line),
364-
column: None,
365-
end_line: None,
366-
end_column: None,
367-
instruction_reference: None,
368-
offset: None,
369-
reason: None,
370-
});
371-
}
372-
}
373-
} else {
374-
let lines = args
375-
.breakpoints
376-
.unwrap_or_default()
377-
.into_iter()
378-
.map(|b| b.line)
379-
.collect::<Vec<_>>();
380-
for line in lines {
381-
results.push(Breakpoint {
382-
id: None,
383-
verified: false,
384-
message: Some("missing source path".to_string()),
385-
source: None,
386-
line: Some(line),
387-
column: None,
388-
end_line: None,
389-
end_column: None,
390-
instruction_reference: None,
391-
offset: None,
392-
reason: None,
393-
});
394-
}
395-
}
396-
let body = SetBreakpointsResponseBody { breakpoints: results };
397-
let resp = DapMessage::Response(Response {
398-
base: ProtocolMessage {
399-
seq: ctx.seq,
400-
type_: "response".to_string(),
401-
},
402-
request_seq: req.base.seq,
403-
success: true,
404-
command: "setBreakpoints".to_string(),
405-
message: None,
406-
body: serde_json::to_value(body)?,
407-
});
408-
ctx.seq += 1;
409-
transport.send(&resp)?;
410-
}
411324
DapMessage::Request(req) if req.command == "launch" => {
412325
ctx.received_launch = true;
413326
let args = req.load_args::<dap::LaunchRequestArguments>()?;

src/db-backend/src/db.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,14 @@ pub struct DbReplay {
785785
pub step_id: StepId,
786786
pub call_key: CallKey,
787787
pub breakpoint_list: Vec<HashMap<usize, Breakpoint>>,
788+
breakpoint_next_id: usize,
788789
}
789790

790791
impl DbReplay {
791792
pub fn new(db: Box<Db>) -> DbReplay {
792793
let mut breakpoint_list: Vec<HashMap<usize, Breakpoint>> = Default::default();
793794
breakpoint_list.resize_with(db.paths.len(), HashMap::new);
794-
DbReplay { db, step_id: StepId(0), call_key: CallKey(0), breakpoint_list }
795+
DbReplay { db, step_id: StepId(0), call_key: CallKey(0), breakpoint_list, breakpoint_next_id: 0 }
795796
}
796797

797798
pub fn step_id_jump(&mut self, step_id: StepId) {
@@ -883,11 +884,11 @@ impl DbReplay {
883884
fn step_continue(&mut self, forward: bool) -> Result<bool, Box<dyn Error>> {
884885
for step in self.db.step_from(self.step_id, forward) {
885886
if !self.breakpoint_list.is_empty() {
886-
if let Some(is_active) = self.breakpoint_list[step.path_id.0]
887+
if let Some(enabled) = self.breakpoint_list[step.path_id.0]
887888
.get(&step.line.into())
888-
.map(|bp| bp.is_active)
889+
.map(|bp| bp.enabled)
889890
{
890-
if is_active {
891+
if enabled {
891892
self.step_id_jump(step.step_id);
892893
// true: has hit a breakpoint
893894
return Ok(true);
@@ -1032,14 +1033,43 @@ impl Replay for DbReplay {
10321033

10331034
fn add_breakpoint(&mut self, path: &str, line: i64) -> Result<Breakpoint, Box<dyn Error>> {
10341035
let path_id_res: Result<PathId, Box<dyn Error>> = self
1035-
.load_path_id(&loc.path)
1036-
.ok_or(format!("can't add a breakpoint: can't find path `{}`` in trace", loc.path).into());
1036+
.load_path_id(path)
1037+
.ok_or(format!("can't add a breakpoint: can't find path `{}`` in trace", path).into());
10371038
let path_id = path_id_res?;
10381039
let inner_map = &mut self.breakpoint_list[path_id.0];
1039-
let breakpoint = Breakpoint { enabled: true, id: self.breakpoint_next_id };
1040-
self.breakpoint_next_i
1041-
inner_map.insert(loc.line, Breakpoint { is_active: true });
1040+
let breakpoint = Breakpoint { enabled: true, id: self.breakpoint_next_id as i64 };
1041+
self.breakpoint_next_id += 1;
1042+
inner_map.insert(line as usize, breakpoint.clone());
1043+
Ok(breakpoint)
10421044
}
1045+
1046+
fn delete_breakpoint(&mut self, _breakpoint: &Breakpoint) -> Result<bool, Box<dyn Error>> {
1047+
// let path_id_res: Result<PathId, Box<dyn Error>> = self
1048+
// .load_path_id(&loc.path)
1049+
// .ok_or(format!("can't add a breakpoint: can't find path `{}`` in trace", loc.path).into());
1050+
// let path_id = path_id_res?;
1051+
// let inner_map = &mut self.breakpoint_list[path_id.0];
1052+
// inner_map.remove(&loc.line);
1053+
todo!()
1054+
}
1055+
1056+
fn delete_breakpoints(&mut self) -> Result<bool, Box<dyn Error>> {
1057+
self.breakpoint_list.clear();
1058+
self.breakpoint_list.resize_with(self.db.paths.len(), HashMap::new);
1059+
Ok(true)
1060+
}
1061+
1062+
fn toggle_breakpoint(&mut self, breakpoint: &Breakpoint) -> Result<Breakpoint, Box<dyn Error>> {
1063+
// let path_id_res: Result<PathId, Box<dyn Error>> = self
1064+
// .load_path_id(&loc.path)
1065+
// .ok_or(format!("can't add a breakpoint: can't find path `{}`` in trace", loc.path).into());
1066+
// let path_id = path_id_res?;
1067+
// if let Some(breakpoint) = self.breakpoint_list[path_id.0].get_mut(&loc.line) {
1068+
let mut toggled_breakpoint = breakpoint.clone();
1069+
toggled_breakpoint.enabled = !toggled_breakpoint.enabled;
1070+
Ok(toggled_breakpoint)
1071+
}
1072+
10431073
fn current_step_id(&mut self) -> StepId {
10441074
self.step_id
10451075
}

src/db-backend/src/handler.rs

Lines changed: 84 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use indexmap::IndexMap;
2-
use std::collections::HashMap;
2+
use std::collections::{HashMap, HashSet};
33
use std::error::Error;
44

55
use log::{error, info, warn};
@@ -52,6 +52,7 @@ pub struct Handler {
5252
pub resulting_dap_messages: Vec<DapMessage>,
5353
pub raw_diff_index: Option<String>,
5454
pub previous_step_id: StepId,
55+
pub breakpoints: HashMap<String, HashSet<i64>>,
5556

5657
pub trace_kind: TraceKind,
5758
pub replay: Box<dyn Replay>,
@@ -114,6 +115,7 @@ impl Handler {
114115
step_lines_loader,
115116
dap_client: DapClient::default(),
116117
previous_step_id: StepId(0),
118+
breakpoints: HashMap::new(),
117119
replay,
118120
ct_rr_args,
119121
load_flow_index: 0,
@@ -893,34 +895,95 @@ impl Handler {
893895
}
894896
}
895897

896-
pub fn add_breakpoint(&mut self, loc: SourceLocation, _task: Task) -> Result<(), Box<dyn Error>> {
897-
self.replay.add_breakpoint(&loc.path, loc.line as i64)?;
898+
pub fn set_breakpoints(&mut self, request: dap::Request, args: dap_types::SetBreakpointsArguments) -> Result<(), Box<dyn Error>> {
899+
let mut results = Vec::new();
900+
self.clear_breakpoints()?;
901+
if let Some(path) = args.source.path.clone() {
902+
let lines: Vec<i64> = if let Some(bps) = args.breakpoints {
903+
bps.into_iter().map(|b| b.line).collect()
904+
} else {
905+
args.lines.unwrap_or_default()
906+
};
907+
908+
for line in lines {
909+
{
910+
let entry = self.breakpoints.entry(path.clone()).or_default();
911+
entry.insert(line);
912+
}
913+
let _ = self.add_breakpoint(
914+
SourceLocation {
915+
path: path.clone(),
916+
line: line as usize,
917+
},
918+
);
919+
results.push(dap_types::Breakpoint {
920+
id: None,
921+
verified: true,
922+
message: None,
923+
source: Some(dap_types::Source {
924+
name: args.source.name.clone(),
925+
path: Some(path.clone()),
926+
source_reference: args.source.source_reference,
927+
presentation_hint: None,
928+
origin: None,
929+
sources: None,
930+
adapter_data: None,
931+
checksums: None,
932+
}),
933+
line: Some(line),
934+
column: None,
935+
end_line: None,
936+
end_column: None,
937+
instruction_reference: None,
938+
offset: None,
939+
reason: None,
940+
});
941+
}
942+
} else {
943+
let lines = args
944+
.breakpoints
945+
.unwrap_or_default()
946+
.into_iter()
947+
.map(|b| b.line)
948+
.collect::<Vec<_>>();
949+
for line in lines {
950+
results.push(dap_types::Breakpoint {
951+
id: None,
952+
verified: false,
953+
message: Some("missing source path".to_string()),
954+
source: None,
955+
line: Some(line),
956+
column: None,
957+
end_line: None,
958+
end_column: None,
959+
instruction_reference: None,
960+
offset: None,
961+
reason: None,
962+
});
963+
}
964+
}
965+
self.respond_dap(request, dap_types::SetBreakpointsResponseBody { breakpoints: results })?;
966+
Ok(())
967+
}
968+
969+
pub fn add_breakpoint(&mut self, loc: SourceLocation) -> Result<(), Box<dyn Error>> {
970+
let _breakpoint = self.replay.add_breakpoint(&loc.path, loc.line as i64)?;
971+
// TODO: map them to id-s in handler so we can do the reverse on delete and let replay work with breakpoints?
898972
Ok(())
899973
}
900974

901-
pub fn delete_breakpoint(&mut self, loc: SourceLocation, _task: Task) -> Result<(), Box<dyn Error>> {
902-
let path_id_res: Result<PathId, Box<dyn Error>> = self
903-
.load_path_id(&loc.path)
904-
.ok_or(format!("can't add a breakpoint: can't find path `{}`` in trace", loc.path).into());
905-
let path_id = path_id_res?;
906-
let inner_map = &mut self.breakpoint_list[path_id.0];
907-
inner_map.remove(&loc.line);
975+
pub fn delete_breakpoint(&mut self, _loc: SourceLocation, _task: Task) -> Result<(), Box<dyn Error>> {
976+
// TODO: load themfrom handler id map: self.replay.delete_breakpoint(loc)
908977
Ok(())
909978
}
910979

911-
pub fn clear_breakpoints(&mut self) {
912-
self.breakpoint_list.clear();
913-
self.breakpoint_list.resize_with(self.db.paths.len(), HashMap::new);
980+
pub fn clear_breakpoints(&mut self) -> Result<(), Box<dyn Error>> {
981+
let _ = self.replay.delete_breakpoints()?;
982+
Ok(())
914983
}
915984

916-
pub fn toggle_breakpoint(&mut self, loc: SourceLocation, _task: Task) -> Result<(), Box<dyn Error>> {
917-
let path_id_res: Result<PathId, Box<dyn Error>> = self
918-
.load_path_id(&loc.path)
919-
.ok_or(format!("can't add a breakpoint: can't find path `{}`` in trace", loc.path).into());
920-
let path_id = path_id_res?;
921-
if let Some(breakpoint) = self.breakpoint_list[path_id.0].get_mut(&loc.line) {
922-
breakpoint.is_active = !breakpoint.is_active;
923-
}
985+
pub fn toggle_breakpoint(&mut self, _loc: SourceLocation, _task: Task) -> Result<(), Box<dyn Error>> {
986+
// TODO: use path,line to id map: self.replay.toggle_breakpoint()?;
924987
Ok(())
925988
}
926989

src/db-backend/src/query.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use serde::{Deserialize, Serialize};
22

3-
use crate::task::{Action, CtLoadLocalsArguments};
3+
use crate::task::{Action, Breakpoint, CtLoadLocalsArguments};
44

55
#[derive(Debug, Clone, Serialize, Deserialize)]
66
#[serde(tag = "kind")]
@@ -11,4 +11,8 @@ pub enum CtRRQuery {
1111
LoadLocals { arg: CtLoadLocalsArguments },
1212
LoadReturnValue,
1313
LoadValue { expression: String },
14+
AddBreakpoint { path: String, line: i64, },
15+
DeleteBreakpoint { breakpoint: Breakpoint, },
16+
DeleteBreakpoints,
17+
ToggleBreakpoint { breakpoint: Breakpoint, },
1418
}

src/db-backend/src/replay.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ pub trait Replay: std::fmt::Debug {
2525
fn jump_to(&mut self, step_id: StepId) -> Result<bool, Box<dyn Error>>;
2626
fn add_breakpoint(&mut self, path: &str, line: i64) -> Result<Breakpoint, Box<dyn Error>>;
2727
fn delete_breakpoint(&mut self, breakpoint: &Breakpoint) -> Result<bool, Box<dyn Error>>;
28+
fn delete_breakpoints(&mut self) -> Result<bool, Box<dyn Error>>;
29+
fn toggle_breakpoint(&mut self, breakpoint: &Breakpoint) -> Result<Breakpoint, Box<dyn Error>>;
2830
fn current_step_id(&mut self) -> StepId;
2931
}

0 commit comments

Comments
 (0)