dwipe 1.0.7__py3-none-any.whl → 2.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dwipe/WipeJobFuture.py ADDED
@@ -0,0 +1,245 @@
1
+ """
2
+ Docstring for dwipe.WipeJobFuture. Probably, only winners here are:
3
+ - Detailed Status Dict - Returns structured status.
4
+ Low risk but not urgent since current status works fine.
5
+ - Custom Pattern Sequences - Adds 0xFF pattern support.
6
+ Low risk but adds complexity.
7
+ """
8
+
9
+ class MaybeSomeDay:
10
+ def __init__(self, device_path, total_size, opts=None, resume_from=0, resume_mode=None):
11
+ """ Performance Throttling """
12
+ # ... existing initialization ...
13
+
14
+ # Performance throttling
15
+ self.max_speed_mbps = getattr(opts, 'max_speed_mbps', 0) # 0 = unlimited
16
+ self.min_speed_mbps = getattr(opts, 'min_speed_mbps', 0) # Minimum speed to trigger stall detection
17
+
18
+ # Stall detection and recovery
19
+ self.stall_timeout = getattr(opts, 'stall_timeout', 300) # Seconds before stall recovery (5 min)
20
+ self.last_progress_time = time.monotonic()
21
+ self.last_progress_bytes = resume_from
22
+
23
+ # Adaptive block sizing
24
+ self.adaptive_block_size = getattr(opts, 'adaptive_block_size', False)
25
+ self.current_write_size = WipeJob.WRITE_SIZE
26
+
27
+ # Temperature monitoring (for SSDs)
28
+ self.check_temperature = getattr(opts, 'check_temperature', False)
29
+ self.last_temp_check = 0
30
+ self.temp_check_interval = 60 # seconds
31
+
32
+ # Energy-efficient mode
33
+ self.energy_saver = getattr(opts, 'energy_saver', False)
34
+
35
+
36
+
37
+
38
+ def _throttle_write_speed(self, bytes_written, start_time):
39
+ """Throttle write speed to specified maximum"""
40
+ if self.max_speed_mbps <= 0:
41
+ return
42
+
43
+ elapsed = time.monotonic() - start_time
44
+ if elapsed <= 0:
45
+ return
46
+
47
+ actual_speed_mbps = (bytes_written / (1024 * 1024)) / elapsed
48
+ if actual_speed_mbps > self.max_speed_mbps:
49
+ # Calculate how long to sleep to hit target speed
50
+ target_time = (bytes_written / (1024 * 1024)) / self.max_speed_mbps
51
+ sleep_time = target_time - elapsed
52
+ if sleep_time > 0:
53
+ time.sleep(sleep_time)
54
+
55
+
56
+
57
+ def _check_ssd_temperature(self):
58
+ """Check SSD temperature and throttle if too hot"""
59
+ if not self.check_temperature:
60
+ return
61
+
62
+ now = time.monotonic()
63
+ if now - self.last_temp_check < self.temp_check_interval:
64
+ return
65
+
66
+ self.last_temp_check = now
67
+
68
+ try:
69
+ # Try to read temperature from SMART or sysfs
70
+ device_name = os.path.basename(self.device_path)
71
+
72
+ # Check sysfs for temperature
73
+ temp_paths = [
74
+ f"/sys/block/{device_name}/device/hwmon/hwmon*/temp1_input",
75
+ f"/sys/block/{device_name}/device/temperature",
76
+ ]
77
+
78
+ for temp_path in temp_paths:
79
+ for path in glob.glob(temp_path):
80
+ try:
81
+ with open(path, 'r') as f:
82
+ temp_millic = int(f.read().strip())
83
+ temp_c = temp_millic // 1000
84
+
85
+ if temp_c > 70: # Throttle if >70°C
86
+ # Reduce speed by 50%
87
+ old_max = self.max_speed_mbps
88
+ self.max_speed_mbps = max(10, old_max // 2)
89
+ if old_max != self.max_speed_mbps:
90
+ print(f"Temperature {temp_c}°C: Throttling to {self.max_speed_mbps} MB/s")
91
+ elif temp_c < 60 and self.max_speed_mbps != getattr(self.opts, 'max_speed_mbps', 0):
92
+ # Restore speed if cooled down
93
+ self.max_speed_mbps = getattr(self.opts, 'max_speed_mbps', 0)
94
+
95
+ except (OSError, ValueError):
96
+ continue
97
+
98
+ except Exception:
99
+ pass
100
+
101
+
102
+
103
+
104
+
105
+
106
+ def _energy_saver_write(self, fd, chunk, is_random_pass):
107
+ """Write with energy saving considerations"""
108
+ if not self.energy_saver:
109
+ return os.write(fd, chunk)
110
+
111
+ # For energy saving:
112
+ # 1. Group writes
113
+ # 2. Add small delays between writes
114
+ # 3. Use larger blocks when possible
115
+
116
+ bytes_written = 0
117
+ chunk_size = len(chunk)
118
+
119
+ while bytes_written < chunk_size:
120
+ write_size = min(self.current_write_size, chunk_size - bytes_written)
121
+ sub_chunk = chunk[bytes_written:bytes_written + write_size]
122
+
123
+ # Write the chunk
124
+ written = os.write(fd, sub_chunk)
125
+ bytes_written += written
126
+
127
+ # Small delay for energy saving
128
+ if bytes_written < chunk_size:
129
+ time.sleep(0.001) # 1ms delay
130
+
131
+ # Update progress
132
+ self.total_written += written
133
+
134
+ return bytes_written
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+ def _adjust_block_size(self, write_success, write_time):
143
+ """Dynamically adjust block size based on performance"""
144
+ if not self.adaptive_block_size:
145
+ return
146
+
147
+ if write_success:
148
+ # Successful write - consider increasing block size
149
+ speed_mbps = (self.current_write_size / (1024 * 1024)) / write_time if write_time > 0 else 0
150
+
151
+ if speed_mbps > 100: # Good speed, try larger blocks
152
+ new_size = min(WipeJob.WRITE_SIZE * 4, self.current_write_size * 2)
153
+ if new_size != self.current_write_size:
154
+ self.current_write_size = new_size
155
+ print(f"Increased block size to {new_size // 1024}KB")
156
+ else:
157
+ # Write failed or slow - reduce block size
158
+ new_size = max(WipeJob.BLOCK_SIZE, self.current_write_size // 2)
159
+ if new_size != self.current_write_size:
160
+ self.current_write_size = new_size
161
+ print(f"Reduced block size to {new_size // 1024}KB")
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+ def get_detailed_status(self):
170
+ """Get detailed status including speed, ETA, and health metrics"""
171
+ elapsed, pct_str, rate_str, eta_str = self.get_status()
172
+
173
+ status = {
174
+ 'elapsed': elapsed,
175
+ 'percentage': pct_str,
176
+ 'rate': rate_str,
177
+ 'eta': eta_str,
178
+ 'bytes_written': self.total_written,
179
+ 'total_bytes': self.total_size * self.passes,
180
+ 'current_pass': self.current_pass + 1 if not self.verify_phase else 'Verifying',
181
+ 'total_passes': self.passes,
182
+ 'verify_phase': self.verify_phase,
183
+ 'verify_result': self.verify_result if hasattr(self, 'verify_result') else None,
184
+ }
185
+
186
+ # Add adaptive block size info if enabled
187
+ if self.adaptive_block_size:
188
+ status['block_size_kb'] = self.current_write_size // 1024
189
+
190
+ # Add throttle info if enabled
191
+ if self.max_speed_mbps > 0:
192
+ status['max_speed_mbps'] = self.max_speed_mbps
193
+
194
+ return status
195
+
196
+
197
+
198
+
199
+ def get_custom_pattern(self, pass_number):
200
+ """Get custom write pattern if specified"""
201
+ custom_patterns = getattr(self.opts, 'custom_patterns', None)
202
+ if custom_patterns and pass_number < len(custom_patterns):
203
+ pattern = custom_patterns[pass_number]
204
+ if pattern == 'random':
205
+ return True
206
+ elif pattern == 'zeros':
207
+ return False
208
+ elif pattern == 'ones':
209
+ # Special pattern: all ones (0xFF)
210
+ return 'ones'
211
+
212
+ # Fall back to standard pattern
213
+ mode_to_use = self.resume_mode if self.resume_mode else self.opts.wipe_mode.replace('+V', '')
214
+ return self.get_pass_pattern(pass_number, mode_to_use)
215
+
216
+
217
+
218
+
219
+ def run_benchmark(self, duration_seconds=30):
220
+ """Run a benchmark to determine optimal settings"""
221
+ print(f"Running benchmark for {duration_seconds} seconds...")
222
+
223
+ benchmark_results = []
224
+ test_sizes = [4*1024, 64*1024, 512*1024, 1024*1024, 4*1024*1024] # 4KB to 4MB
225
+
226
+ for test_size in test_sizes:
227
+ self.current_write_size = test_size
228
+ start_time = time.monotonic()
229
+ bytes_written = 0
230
+
231
+ # Test write for duration_seconds
232
+ while time.monotonic() - start_time < duration_seconds:
233
+ # Perform test write
234
+ # ... benchmark logic ...
235
+ pass
236
+
237
+ speed_mbps = bytes_written / (1024 * 1024) / duration_seconds
238
+ benchmark_results.append((test_size, speed_mbps))
239
+ print(f" Block size {test_size//1024}KB: {speed_mbps:.2f} MB/s")
240
+
241
+ # Find optimal block size
242
+ optimal_size = max(benchmark_results, key=lambda x: x[1])[0]
243
+ print(f"Optimal block size: {optimal_size//1024}KB")
244
+
245
+ return optimal_size