Skip to content

Commit fe80145

Browse files
committed
remove more unnecessary code
1 parent 7b2c71d commit fe80145

File tree

10 files changed

+138
-1550
lines changed

10 files changed

+138
-1550
lines changed

docs/make.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ makedocs(;
2020
"Internals & Design" => "internals.md",
2121
"HDF5 Compatibility" => "hdf5compat.md",
2222
"Advanced Usage" => "advanced.md",
23-
"Dataset Links" => "external_links.md"
23+
"Dataset Links" => "external_links.md",
2424
"Legacy" => "legacy.md",
2525
"Troubleshooting" => "troubleshooting.md"
2626
],

docs/src/external_links.md

Lines changed: 17 additions & 190 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# External Links and Soft Links in JLD2
22

3-
JLD2 now supports external links and soft links, enabling cross-file references and flexible file organization patterns. This feature is fully compatible with the HDF5 specification and standard HDF5 tools.
3+
JLD2 supports external links and soft links, enabling cross-file references and flexible file organization patterns. This feature is fully compatible with the HDF5 specification and standard HDF5 tools.
44

55
## Overview
66

@@ -10,35 +10,6 @@ JLD2 supports three types of links:
1010
- **Soft Links**: Path-based references resolved at access time within the same file
1111
- **External Links**: References to objects in different HDF5/JLD2 files
1212

13-
## Quick Start
14-
15-
### Creating External Links
16-
17-
```julia
18-
using JLD2
19-
20-
# Create an external data file
21-
jldsave("data.jld2";
22-
temperature=[23.5, 24.1, 22.8, 25.3],
23-
pressure=[1013.2, 1012.8, 1014.1, 1013.5])
24-
25-
# Create main file with external link
26-
jldopen("main.jld2", "w") do f
27-
f["local_data"] = [1, 2, 3, 4, 5]
28-
29-
# Create external links
30-
create_external_link!(f, "external_temp", "data.jld2", "/temperature")
31-
create_external_link!(f, "external_pressure", "data.jld2", "/pressure")
32-
end
33-
34-
# Access external data transparently
35-
jldopen("main.jld2", "r") do f
36-
local_data = f["local_data"] # [1, 2, 3, 4, 5]
37-
external_temp = f["external_temp"] # [23.5, 24.1, 22.8, 25.3]
38-
external_press = f["external_pressure"] # [1013.2, 1012.8, 1014.1, 1013.5]
39-
end
40-
```
41-
4213
### Creating Soft Links
4314

4415
```julia
@@ -60,173 +31,29 @@ jldopen("example.jld2", "r") do f
6031
end
6132
```
6233

63-
## API Reference
64-
65-
### External Links
66-
67-
#### `create_external_link!(file_or_group, name, external_file, object_path)`
68-
69-
Create an external link pointing to an object in another file.
70-
71-
**Parameters:**
72-
- `file_or_group`: JLDFile or Group to create the link in
73-
- `name`: Name for the new link
74-
- `external_file`: Path to the external HDF5/JLD2 file
75-
- `object_path`: Path to the object within the external file (should start with "/")
76-
77-
**Example:**
78-
```julia
79-
jldopen("main.jld2", "w") do f
80-
create_external_link!(f, "remote_data", "../shared/data.jld2", "/measurements/temperature")
81-
end
82-
```
83-
84-
### Soft Links
85-
86-
#### `create_soft_link!(file_or_group, name, target_path)`
87-
88-
Create a soft link pointing to a path within the same file.
89-
90-
**Parameters:**
91-
- `file_or_group`: JLDFile or Group to create the link in
92-
- `name`: Name for the new link
93-
- `target_path`: Path to the target object (absolute path starting with "/")
94-
95-
**Example:**
96-
```julia
97-
jldopen("data.jld2", "w") do f
98-
f["original_data"] = [1, 2, 3]
99-
create_soft_link!(f, "data_shortcut", "/original_data")
100-
end
101-
```
102-
103-
## Advanced Usage
104-
105-
### Working with Groups
106-
107-
```julia
108-
jldopen("structured.jld2", "w") do f
109-
# Create nested structure
110-
exp_group = JLD2.Group(f, "experiment")
111-
data_group = JLD2.Group(exp_group, "data")
112-
results_group = JLD2.Group(exp_group, "results")
113-
114-
data_group["raw"] = collect(1:100)
115-
results_group["processed"] = collect(1:100) .^ 2
116-
117-
# Create soft links for easier access
118-
create_soft_link!(f, "raw_data", "/experiment/data/raw")
119-
create_soft_link!(f, "final_results", "/experiment/results/processed")
120-
121-
# External link to shared calibration data
122-
create_external_link!(f, "calibration", "calibration.jld2", "/standard_curve")
123-
end
124-
```
125-
126-
### Cross-File Data Workflows
34+
### Creating External Links
12735

12836
```julia
129-
# Step 1: Create base data
130-
jldsave("measurements.jld2";
131-
voltage=[1.2, 1.5, 1.8, 2.1],
132-
current=[0.1, 0.2, 0.3, 0.4])
133-
134-
# Step 2: Create analysis file with external links
135-
jldopen("analysis.jld2", "w") do f
136-
# Link to external measurements
137-
create_external_link!(f, "voltage_data", "measurements.jld2", "/voltage")
138-
create_external_link!(f, "current_data", "measurements.jld2", "/current")
139-
140-
# Process the external data and save results locally
141-
voltage = f["voltage_data"] # Transparently loads from external file
142-
current = f["current_data"]
143-
144-
f["resistance"] = voltage ./ current
145-
f["power"] = voltage .* current
146-
147-
# Create soft links to results
148-
create_soft_link!(f, "R", "/resistance")
149-
create_soft_link!(f, "P", "/power")
150-
end
151-
152-
# Step 3: Access everything through high-level API
153-
results = load("analysis.jld2")
154-
# results contains: voltage_data, current_data, resistance, power, R, P
155-
```
37+
using JLD2
15638

157-
### Error Handling
39+
# Create an external data file
40+
jldsave("data.jld2";
41+
temperature=[23.5, 24.1, 22.8, 25.3],
42+
pressure=[1013.2, 1012.8, 1014.1, 1013.5])
15843

159-
```julia
44+
# Create main file with external link
16045
jldopen("main.jld2", "w") do f
161-
try
162-
# This will fail if the external file doesn't exist
163-
create_external_link!(f, "missing", "nonexistent.jld2", "/data")
164-
catch e
165-
println("External link creation failed: $e")
166-
end
167-
168-
try
169-
# This will fail if accessed and the path doesn't exist
170-
create_soft_link!(f, "broken", "/nonexistent/path")
171-
f["broken"] # Error occurs here during access
172-
catch e
173-
println("Soft link resolution failed: $e")
174-
end
175-
end
176-
```
177-
178-
## Performance Characteristics
179-
180-
- **Hard Links**: ~0.03ms per access (baseline)
181-
- **Soft Links**: ~0.001ms per access (cached resolution)
182-
- **External Links**: ~0.2ms per access (with file handle caching)
183-
- **External File Caching**: 200-300x speedup for repeated access to same external file
184-
185-
## HDF5 Tool Compatibility
186-
187-
Files with external and soft links are fully compatible with standard HDF5 tools:
188-
189-
```bash
190-
# View file structure showing links
191-
h5dump -H main.jld2
192-
193-
# Access data through external links
194-
h5dump -d /external_temp main.jld2
195-
196-
# Validate file structure
197-
h5debug main.jld2
198-
```
199-
200-
## Security Considerations
201-
202-
- **Path Validation**: External file paths are validated to prevent directory traversal attacks
203-
- **Relative Paths**: External links support relative paths resolved from the current file's directory
204-
- **Access Control**: Optional access policies can be configured for production environments
205-
206-
## Best Practices
207-
208-
1. **Use Relative Paths**: When possible, use relative paths for external links to make file sets portable
209-
2. **Error Handling**: Always handle potential errors when accessing external links
210-
3. **File Organization**: Use external links to create modular data workflows
211-
4. **Performance**: External links are cached automatically - no manual optimization needed
212-
5. **HDF5 Compatibility**: Files with links can be read by any HDF5-compatible tool
213-
214-
## Migration from Hard Links
215-
216-
Existing JLD2 code continues to work unchanged. To add link features:
46+
f["local_data"] = [1, 2, 3, 4, 5]
21747

218-
```julia
219-
# Before (hard links only)
220-
jldopen("data.jld2", "w") do f
221-
f["dataset"] = data
48+
# Create external links
49+
create_external_link!(f, "external_temp", "data.jld2", "/temperature")
50+
create_external_link!(f, "external_pressure", "data.jld2", "/pressure")
22251
end
22352

224-
# After (with links for better organization)
225-
jldopen("data.jld2", "w") do f
226-
f["raw_dataset"] = data
227-
create_soft_link!(f, "dataset", "/raw_dataset") # Alias for compatibility
228-
create_external_link!(f, "reference", "standards.jld2", "/reference_data")
53+
# Access external data transparently
54+
jldopen("main.jld2", "r") do f
55+
local_data = f["local_data"] # [1, 2, 3, 4, 5]
56+
external_temp = f["external_temp"] # [23.5, 24.1, 22.8, 25.3]
57+
external_press = f["external_pressure"] # [1013.2, 1012.8, 1014.1, 1013.5]
22958
end
23059
```
231-
232-
External links and soft links provide powerful tools for organizing complex data workflows while maintaining full backward compatibility with existing JLD2 code.

src/JLD2.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ function jldopen(fname::AbstractString, wr::Bool, create::Bool, truncate::Bool,
184184
parallel_read::Bool=false,
185185
plain::Bool=false
186186
) where T<:Union{Type{IOStream},Type{MmapIO}}
187-
187+
188188
mmaparrays && @warn "mmaparrays keyword is currently ignored" maxlog = 1
189189
filters = Filters.normalize_filters(compress)
190190

@@ -510,7 +510,6 @@ end
510510

511511
include("object_headers.jl")
512512
include("headermessages.jl")
513-
include("path_resolution.jl")
514513
include("external_files.jl")
515514
include("groups.jl")
516515
include("dataspaces.jl")

src/explicit_datasets.jl

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,8 @@ function get_dataset(g::Group, name::String)
208208
"Use f[\"", name, "\"] to access the external data directly."
209209
)))
210210
elseif isa(link, SoftLink)
211-
# For soft links, check if they point to a regular dataset within the same file
212-
resolved_path = resolve_soft_link_path(group_path(g), link.path)
213-
# Use lookup_link for the resolved path as well to be consistent
214-
target_link = lookup_link(f.root_group, resolved_path[2:end]) # Remove leading '/'
215-
if target_link !== nothing && isa(target_link, HardLink)
211+
target_link = lookup_link(g, link.path)
212+
if isa(target_link, HardLink)
216213
# This is a soft link to a regular dataset within the same file - allow it
217214
return get_dataset(f, target_link.target, g, name)
218215
else
@@ -280,23 +277,21 @@ write_header_message(io, f, msg::Pair{String, AbstractLink}, _=nothing) =
280277
281278
Calculate the size of a link message for the given link type.
282279
"""
283-
function message_size_for_link(name::String, link::AbstractLink)
284-
if isa(link, HardLink)
285-
return jlsizeof(Val(HmLinkMessage); link_name=name)
286-
elseif isa(link, SoftLink)
287-
soft_link_data = Vector{UInt8}(link.path)
288-
flags = UInt8(0x10 | 0x08 | size_flag(sizeof(name))) # 0x08 = bit 3 set
289-
return jlsizeof(Val(HmLinkMessage); link_name=name, flags=flags,
290-
link_type=UInt8(1), link_info_size=UInt16(length(soft_link_data)),
291-
soft_link=soft_link_data)
280+
function message_size_for_link(link_name::String, link::AbstractLink)
281+
isa(link, HardLink) && return jlsizeof(Val(HmLinkMessage); link_name)
282+
283+
flags = UInt8(0x10 | 0x08 | size_flag(sizeof(link_name)))
284+
if isa(link, SoftLink)
285+
return jlsizeof(Val(HmLinkMessage); link_name, flags,
286+
link_type=UInt8(1),
287+
link_info_size=sizeof(link.path),
288+
soft_link=UInt8[])
292289
elseif isa(link, ExternalLink)
293290
# External link data: two null-terminated strings
294-
external_data = vcat(0x00, Vector{UInt8}(link.file_path), 0x00,
295-
Vector{UInt8}(link.object_path), 0x00)
296-
flags = UInt8(0x10 | 0x08 | size_flag(sizeof(name))) # 0x08 = bit 3 set
297-
return jlsizeof(Val(HmLinkMessage); link_name=name, flags=flags,
298-
link_type=UInt8(64), link_info_size=UInt16(length(external_data)),
299-
external_link=external_data)
291+
return jlsizeof(Val(HmLinkMessage); link_name, flags,
292+
link_type=UInt8(64),
293+
link_info_size=3+sizeof(link.file_path)+sizeof(link.object_path),
294+
external_link=UInt8[])
300295
else
301296
throw(UnsupportedFeatureException("Unsupported link type: $(typeof(link))"))
302297
end
@@ -307,27 +302,20 @@ end
307302
308303
Write a link message for the given link type to the I/O stream.
309304
"""
310-
function write_link_message(io, name::String, link::AbstractLink)
305+
function write_link_message(io, link_name::String, link::AbstractLink)
311306
if isa(link, HardLink)
312-
write_header_message(io, Val(HmLinkMessage); link_name=name, target=link.target)
313-
elseif isa(link, SoftLink)
314-
soft_link_data = Vector{UInt8}(link.path)
315-
# Set flags with bit 3 to indicate link_type is present
316-
flags = UInt8(0x10 | 0x08 | size_flag(sizeof(name))) # 0x08 = bit 3 set
317-
write_header_message(io, Val(HmLinkMessage); link_name=name, flags=flags,
318-
link_type=UInt8(1), link_info_size=UInt16(length(soft_link_data)),
319-
soft_link=soft_link_data)
307+
return write_header_message(io, Val(HmLinkMessage); link_name, link.target)
308+
end
309+
flags = UInt8(0x10 | 0x08 | size_flag(sizeof(link_name)))
310+
if isa(link, SoftLink)
311+
soft_link = Vector{UInt8}(link.path)
312+
write_header_message(io, Val(HmLinkMessage); link_name, flags, link_type=1, soft_link)
320313
elseif isa(link, ExternalLink)
321314
# External link data: two null-terminated strings
322-
external_data = vcat(0x00, Vector{UInt8}(link.file_path), 0x00,
315+
external_link = vcat(0x00, Vector{UInt8}(link.file_path), 0x00,
323316
Vector{UInt8}(link.object_path), 0x00)
324-
# Set flags with bit 3 to indicate link_type is present
325-
flags = UInt8(0x10 | 0x08 | size_flag(sizeof(name))) # 0x08 = bit 3 set
326-
write_header_message(io, Val(HmLinkMessage); link_name=name, flags=flags,
327-
link_type=UInt8(64), link_info_size=UInt16(length(external_data)),
328-
external_link=external_data)
329-
else
330-
throw(UnsupportedFeatureException("Unsupported link type: $(typeof(link))"))
317+
write_header_message(io, Val(HmLinkMessage); link_name, flags, link_type=64,
318+
external_link)
331319
end
332320
end
333321

0 commit comments

Comments
 (0)