ReactOS 0.4.15-dev-8100-g1887773
Defragment.cpp
Go to the documentation of this file.
1#include "Defragment.h"
2
3
4// Ahh yes I ripped this from my old Findupes project :)
5// Fits a path name, composed of a path (i.e. "c:\blah\blah\cha\cha") and a filename ("stuff.txt")
6// and fits it to a given length. If it has to truncate it will first truncate from the path,
7// substituting in periods. So you might end up with something like:
8// C:\Program Files\Micro...\Register.exe
9int FitName (wchar_t *destination, const wchar_t *path, const wchar_t *filename, uint32 totalWidth)
10{
11 uint32 pathLen=0;
12 uint32 fnLen=0;
13 uint32 halfTotLen=0;
14 uint32 len4fn=0; /* number of chars remaining for filename after path is applied */
15 uint32 len4path=0; /* number of chars for path before filename is applied */
16 wchar_t fmtStrPath[20]=L"";
17 wchar_t fmtStrFile[20]=L"";
18 wchar_t fmtString[40]=L"";
19
20 /*
21 assert (destination != NULL);
22 assert (path != NULL);
23 assert (filename != NULL);
24 assert (totalWidth != 0);
25 */
26
27 pathLen = wcslen(path);
28 fnLen = wcslen(filename);
29 if (!(totalWidth % 2))
30 halfTotLen=totalWidth / 2;
31 else
32 halfTotLen=(totalWidth-1) / 2; /* -1 because otherwise (halfTotLen*2) ==
33(totalWidth+1) which wouldn't be good */
34
35 /* determine how much width the path and filename each get */
36 if ( (pathLen >= halfTotLen) && (fnLen < halfTotLen) )
37 {
38 len4fn = fnLen;
39 len4path = (totalWidth - len4fn);
40 }
41
42 if ( (pathLen < halfTotLen) && (fnLen < halfTotLen) )
43 {
44 len4fn = fnLen;
45 len4path = pathLen;
46 }
47
48 if ( (pathLen >= halfTotLen) && (fnLen >= halfTotLen) )
49 {
50 len4fn = halfTotLen;
51 len4path = halfTotLen;
52 }
53
54 if ( (pathLen < halfTotLen) && (fnLen >= halfTotLen) )
55 {
56 len4path = pathLen;
57 len4fn = (totalWidth - len4path);
58 }
59 /*
60 if halfTotLen was adjusted above to avoid a rounding error, give the
61 extra wchar_t to the filename
62 */
63 if (halfTotLen < (totalWidth/2)) len4path++;
64
65 if (pathLen > len4path) swprintf (fmtStrPath, L"%%.%ds...\\", len4path-4);
66 else
67 swprintf (fmtStrPath, L"%%s");
68
69 if (fnLen > len4fn) swprintf (fmtStrFile, L"%%.%ds...", len4fn-3);
70 else
71 swprintf (fmtStrFile, L"%%s");
72
73 wcscpy (fmtString, fmtStrPath);
74 wcscat (fmtString, fmtStrFile);
75 /*swprintf (fmtString, L"%s%s", fmtStrPath, fmtStrFile);*/
76 swprintf (destination, fmtString, path,filename);
77
78 return (1);
79}
80
81Defragment::Defragment (wstring Name, DefragType DefragMethod)
82{
84 DoLimitLength = true;
85 Error = false;
86 Done = false;
87 PleaseStop = false;
88 PleasePause = false;
90 StatusPercent = 0.0f;
92
93 SetStatusString (L"Opening volume " + Name);
94 if (!Volume.Open (Name))
95 {
96 SetStatusString (L"Error opening volume " + Name);
97 Error = true;
98 Done = true;
99 StatusPercent = 100.0f;
100 }
101
102 return;
103}
104
105
107{
108 if (!IsDoneYet ())
109 {
110 Stop ();
111 while (!IsDoneYet() && !HasError())
112 {
113 SetStatusString (L"Waiting for thread to stop ...");
114 Sleep (150);
115 }
116 }
117
118 Volume.Close ();
119 return;
120}
121
122
123void Defragment::SetStatusString (wstring NewStatus)
124{
125 Lock ();
126 StatusString = NewStatus;
127 Unlock ();
128
129 return;
130}
131
132
134{
135 wstring ReturnVal;
136
137 Lock ();
138 ReturnVal = StatusString;
139 Unlock ();
140
141 return (ReturnVal);
142}
143
144
146{
147 return (StatusPercent);
148}
149
150
152{
153 return (Done);
154}
155
156
158{
159 uint32 i;
160 uint64 FirstFreeLCN;
161 uint64 TotalClusters;
162 uint64 ClustersProgress;
163 wchar_t PrintName[80];
164 int Width = 70;
165
166 if (Error)
167 goto DoneDefrag;
168
169 // First thing: build a file list.
170 SetStatusString (L"Getting volume bitmap");
171 if (!Volume.GetBitmap())
172 {
173 SetStatusString (L"Could not get volume " + DriveName + L" bitmap");
174 Error = true;
175 goto DoneDefrag;
176 }
177
179
180 if (PleaseStop)
181 goto DoneDefrag;
182
183 SetStatusString (L"Obtaining volume geometry");
184 if (!Volume.ObtainInfo ())
185 {
186 SetStatusString (L"Could not obtain volume " + DriveName + L" geometry");
187 Error = true;
188 goto DoneDefrag;
189 }
190
191 if (PleaseStop)
192 goto DoneDefrag;
193
194 SetStatusString (L"Building file database for volume " + DriveName);
196 {
197 SetStatusString (L"Could not build file database for volume " + DriveName);
198 Error = true;
199 goto DoneDefrag;
200 }
201
202 if (PleaseStop)
203 goto DoneDefrag;
204
205 SetStatusString (L"Analyzing database for " + DriveName);
206 TotalClusters = 0;
207 for (i = 0; i < Volume.GetDBFileCount(); i++)
208 {
209 TotalClusters += Volume.GetDBFile(i).Clusters;
210 }
211
212 // Defragment!
213 ClustersProgress = 0;
214
215 // Find first free LCN for speedier searches ...
216 Volume.FindFreeRange (0, 1, FirstFreeLCN);
217
218 if (PleaseStop)
219 goto DoneDefrag;
220
221 // Analyze?
222 if (Method == DefragAnalyze)
223 {
224 uint32 j;
225
227
228 Report.FraggedFiles.clear ();
229 Report.UnfraggedFiles.clear ();
230 Report.UnmovableFiles.clear ();
231
235
240
241 for (j = 0; j < Volume.GetDBFileCount(); j++)
242 {
244
246
247 Report.FilesFragments += max ((size_t)1, Info.Fragments.size()); // add 1 fragment even for 0 bytes/0 cluster files
248
249 if (Info.Attributes.Process == 0)
250 continue;
251
252 SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name);
253
254 Report.FilesSizeClusters += Info.Clusters;
255 Report.FilesSizeBytes += Info.Size;
256
257 if (Info.Attributes.Unmovable == 1)
258 Report.UnmovableFiles.push_back (j);
259
260 if (Info.Fragments.size() > 1)
261 Report.FraggedFiles.push_back (j);
262 else
263 Report.UnfraggedFiles.push_back (j);
264
265 StatusPercent = ((double)j / (double)Report.FilesCount) * 100.0f;
266 }
267
271 Report.PercentFragged = 100.0f * ((double)(signed)Report.FraggedFiles.size() / (double)(signed)Report.FilesCount);
272
273 uint64 Percent;
274 Percent = (10000 * Report.FilesSlackBytes) / Report.FilesSizeOnDisk;
275 Report.PercentSlack = (double)(signed)Percent / 100.0f;
276 }
277 else
278 // Go through all the files and ... defragment them!
279 for (i = 0; i < Volume.GetDBFileCount(); i++)
280 {
282 bool Result;
283 uint64 TargetLCN;
284 uint64 PreviousClusters;
285
286 // What? They want us to pause? Oh ok.
287 if (PleasePause)
288 {
289 SetStatusString (L"Paused");
290 PleasePause = false;
291
292 while (PleasePause == false)
293 {
294 Sleep (50);
295 }
296
297 PleasePause = false;
298 }
299
300 if (PleaseStop)
301 {
302 SetStatusString (L"Stopping");
303 break;
304 }
305
306 //
308
309 PreviousClusters = ClustersProgress;
310 ClustersProgress += Info.Clusters;
311
312 if (Info.Attributes.Process == 0)
313 continue;
314
315 if (!DoLimitLength)
316 SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name);
317 else
318 {
319 FitName (PrintName, Volume.GetDBDir (Info.DirIndice).c_str(), Info.Name.c_str(), Width);
321 }
322
323 // Calculate percentage complete
324 StatusPercent = 100.0f * double((double)PreviousClusters / (double)TotalClusters);
325
326 // Can't defrag directories yet
327 if (Info.Attributes.Directory == 1)
328 continue;
329
330 // Can't defrag 0 byte files :)
331 if (Info.Fragments.empty())
332 continue;
333
334 // If doing fast defrag, skip non-fragmented files
335 // Note: This assumes that the extents stored in Info.Fragments
336 // are consolidated. I.e. we assume it is NOT the case that
337 // two extents account for a sequential range of (non-
338 // fragmented) clusters.
339 if (Info.Fragments.size() == 1 && Method == DefragFast)
340 continue;
341
342 // Otherwise, defrag0rize it!
343 int Retry = 3; // retry a few times
344 while (Retry > 0)
345 {
346 // Find a place that can fit the file
347 Result = Volume.FindFreeRange (FirstFreeLCN, Info.Clusters, TargetLCN);
348
349 // If yes, try moving it
350 if (Result)
351 {
352 // If we're doing an extensive defrag and the file is already defragmented
353 // and if its new location would be after its current location, don't
354 // move it.
355 if (Method == DefragExtensive && Info.Fragments.size() == 1 &&
356 TargetLCN > Info.Fragments[0].StartLCN)
357 {
358 Retry = 1;
359 }
360 else
361 {
362 if (Volume.MoveFileDumb (i, TargetLCN))
363 {
364 Retry = 1; // yay, all done with this file.
365 Volume.FindFreeRange (0, 1, FirstFreeLCN);
366 }
367 }
368 }
369
370 // New: Only update bitmap if it's older than 15 seconds
371 if ((GetTickCount() - LastBMPUpdate) < 15000)
372 Retry = 1;
373 else
374 if (!Result || Retry != 1)
375 { // hmm. Wait for a moment, then update the drive bitmap
376 //SetStatusString (L"(Reobtaining volume " + DriveName + L" bitmap)");
377
378 if (!DoLimitLength)
379 {
380 SetStatusString (GetStatusString() + wstring (L" ."));
381 }
382
383 if (Volume.GetBitmap ())
384 {
386
387 if (!DoLimitLength)
388 SetStatusString (Volume.GetDBDir (Info.DirIndice) + Info.Name);
389 else
391
392 Volume.FindFreeRange (0, 1, FirstFreeLCN);
393 }
394 else
395 {
396 SetStatusString (L"Could not re-obtain volume " + DriveName + L" bitmap");
397 Error = true;
398 }
399 }
400
401 Retry--;
402 }
403
404 if (Error == true)
405 break;
406 }
407
408DoneDefrag:
409 wstring OldStatus;
410
411 OldStatus = GetStatusString ();
412 StatusPercent = 99.999999f;
413 SetStatusString (L"Closing volume " + DriveName);
414 Volume.Close ();
415 StatusPercent = 100.0f;
416
417 // If there was an error then the wstring has already been set
418 if (Error)
419 SetStatusString (OldStatus);
420 else
421 if (PleaseStop)
422 SetStatusString (L"Volume " + DriveName + L" defragmentation was stopped");
423 else
424 SetStatusString (L"Finished defragmenting " + DriveName);
425
426 Done = true;
427
428 return;
429}
430
431
433{
434 Lock ();
435 SetStatusString (L"Pausing ...");
436 PleasePause = true;
437 Unlock ();
438
439 return;
440}
441
442
444{
445 Lock ();
446 SetStatusString (L"Stopping ...");
447 PleaseStop = true;
448 Unlock ();
449
450 return;
451}
452
453
455{
456 return (Error);
457}
458
int FitName(wchar_t *destination, const wchar_t *path, const wchar_t *filename, uint32 totalWidth)
Definition: Defragment.cpp:9
int FitName(wchar_t *destination, const wchar_t *path, const wchar_t *filename, uint32 totalWidth)
Definition: Defragment.cpp:9
DefragType
Definition: Unfrag.h:67
@ DefragExtensive
Definition: Unfrag.h:70
@ DefragAnalyze
Definition: Unfrag.h:71
@ DefragFast
Definition: Unfrag.h:69
struct NameRec_ * Name
Definition: cdprocs.h:460
unsigned int uint32
Definition: types.h:32
void TogglePause(void)
Definition: Defragment.cpp:432
DriveVolume Volume
Definition: Defragment.h:79
void Unlock(void)
Definition: Defragment.h:63
bool Done
Definition: Defragment.h:85
DWORD LastBMPUpdate
Definition: Defragment.h:74
bool IsDoneYet(void)
Definition: Defragment.cpp:151
bool PleaseStop
Definition: Defragment.h:86
wstring DriveName
Definition: Defragment.h:78
DefragReport Report
Definition: Defragment.h:75
void Lock(void)
Definition: Defragment.h:62
bool PleasePause
Definition: Defragment.h:87
void Start(void)
Definition: Defragment.cpp:157
bool Error
Definition: Defragment.h:84
DefragType Method
Definition: Defragment.h:77
bool DoLimitLength
Definition: Defragment.h:76
wstring GetStatusString(void)
Definition: Defragment.cpp:133
DefragType DefragMethod
Definition: Defragment.h:88
void Stop(void)
Definition: Defragment.cpp:443
Defragment(wstring Name, DefragType DefragMethod)
Definition: Defragment.cpp:81
double StatusPercent
Definition: Defragment.h:82
void SetStatusString(wstring NewStatus)
Definition: Defragment.cpp:123
wstring StatusString
Definition: Defragment.h:80
bool HasError(void)
Definition: Defragment.cpp:454
double GetStatusPercent(void)
Definition: Defragment.cpp:145
FileInfo & GetDBFile(uint32 Indice)
void Close(void)
Definition: DriveVolume.cpp:21
bool Open(wstring Name)
Definition: DriveVolume.cpp:42
VolumeInfo GetVolumeInfo(void)
Definition: DriveVolume.h:109
uint32 GetDBFileCount(void)
wstring & GetDBDir(uint32 Indice)
bool BuildFileList(bool &QuitMonitor, double &Progress)
bool GetBitmap(void)
uint32 GetDBDirCount(void)
bool MoveFileDumb(uint32 FileIndice, uint64 NewLCN)
bool FindFreeRange(uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult)
bool ObtainInfo(void)
wstring GetRootPath(void)
Definition: DriveVolume.h:111
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
#define swprintf
Definition: precomp.h:40
unsigned long long uint64
Definition: platform.h:18
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
const char * filename
Definition: ioapi.h:137
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
#define L(x)
Definition: ntvdm.h:50
#define signed
Definition: prototyp.h:114
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
void PrintName(FILE *fileDest, EXPORT *pexp, PSTRING pstr, int fDeco)
Definition: spec2def.c:540
uint64 FilesSizeOnDisk
Definition: Defragment.h:27
uint64 FilesSizeClusters
Definition: Defragment.h:28
vector< uint32 > UnmovableFiles
Definition: Defragment.h:37
double PercentSlack
Definition: Defragment.h:33
vector< uint32 > UnfraggedFiles
Definition: Defragment.h:36
double PercentFragged
Definition: Defragment.h:32
vector< uint32 > FraggedFiles
Definition: Defragment.h:35
uint32 FilesFragments
Definition: Defragment.h:30
uint64 FilesSlackBytes
Definition: Defragment.h:29
uint64 FilesCount
Definition: Defragment.h:25
wstring RootPath
Definition: Defragment.h:22
uint64 FilesSizeBytes
Definition: Defragment.h:26
uint64 DirsCount
Definition: Defragment.h:24
double AverageFragments
Definition: Defragment.h:31
uint64 DiskSizeBytes
Definition: Defragment.h:23
uint64 Clusters
Definition: DriveVolume.h:57
uint64 TotalBytes
Definition: DriveVolume.h:74
uint32 ClusterSize
Definition: DriveVolume.h:73
#define max(a, b)
Definition: svc.c:63
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:89
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409