|
Hi There,
I am busy with an application that needs to pre-allocate all available space on a clean-formatted dedicated drive to datafiles of a fixed size. At this stage I am doing something like:
<br />
while (freediskspace < allocatespace)<br />
{<br />
}<br />
Creating the files like this, one after the other, I would expect that there would be minimal (if any) fragmentation on the disk. However, when I then run Microsoft Defragment to analyze the disk it reports that just about all the created files are fragmented and some of them even into 93 fragments.
I have experimented with different allocation size, writing different chunk size at a time, etc, but all of them result in fragmented files.
My question is now very simply this: How do I create files on a clean-formatted drive without them becoming fragmented ??
Thanks
OD
|
|
|
|
|
Wow, that's fascinating. Those results surprise me.
I would guess that the severe fragmenting is due to the delayed write cache that Windows uses. It sees you madly writing data, so it waits before it actually commits anything to disk. But when it does, whatever algorithm it uses causes the files to get written haphazardly, resulting in fragmentation.
I made all that up as I went along, by the way.
Anyway, there are Flush functions that may force the file buffers to disk. If you're using fopen() there is a fflush() that may do what I'm suggesting. There is also CFile::Flush() if you swing that way. I think every method of file writing has an associated flush function.
I would recommend flushing each file at the end of each loop, maybe at the end of each block write. Just to see what happens.
Let us know what you find!
|
|
|
|
|
try instead of
od@ananzi.co.za wrote:
// Write to file 10 times, (allocatespace/10) bytes at a time
write to memory until done (alloc/realloc all you want)
dump the memory to the file at once.
Otherwise I do not think you have contol over it, unless you want to write kernel driver.
|
|
|
|
|
od@ananzi.co.za wrote:
My question is now very simply this: How do I create files on a clean-formatted drive without them becoming fragmented ??
There's no guarantee that you can. It's totally up to the file system as to how it splits up a file.
|
|
|
|
|
od@ananzi.co.za wrote:
My question is now very simply this: How do I create files on a clean-formatted drive without them becoming fragmented ??
Use FAT32... NTFS should be renamed to SFFS or self fragmenting file system...
Actually I think there is a way by setting the size of the file when you create it but I am not sure...
John
|
|
|
|
|
Indeed, setting the file size might help. I don't know the api call, but for MFC it is: CFile::SetLength()
A student knows little about a lot.
A professor knows a lot about little.
I know everything about nothing.
|
|
|
|
|
SetFilePointer() /SetEndOfFile() for Win32
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
I dont know about the new versions of NTFS, but in NT4 it reserved the same amount as the file use, as free space after the file. That way a file could grow to double size without being fragmented.
But... When the disk got more that half full, the reserved spaces was taked to use, and some files became very fragmented because some of the reserved spaces was quite small...
Try to create file at half size, and then expand it to full size, if NTFS still use the same algorithm, this should help
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
That is very fascinating!
I offer you one of my scheme although it perhaps sounds not very OK
1.Marked the fragments with fragment serial number. Send the fragments with serial number, the fragment size and the total size.
2.When receiving a fragment analize it and then allocate the total space and the fragment postion. After this, store the fragment in the special position
3.The task is finished when the last fragment is stored.
This way maybe minimize the number of fragments
|
|
|
|
|
Create the file, seek to the position corresponding to how long you want the file and call SetEndOfFile() to set the new size of the file:
hFile = CreateFile(...);
SetFilePointer(hFile, 1048576, NULL, FILE_BEGIN);
SetEndOfFile(hFile); Of course, you'll need to perform error checking as well, and you'll need to change the value in SetFilePointer() to be the desired size of the file. I can't gaurantee that it will create unfragmented files (this is really up to Windows), but it's probably the most likely to if there is enough unfragmented space. Just keep in mind that the contents of the file are undefined, so you might want to go back and write over the file to initialise it. Some of the other guys have good suggestions, so try them as well
Hope this helps,
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Hi Guys,
Thanks for all the comments. Just one or two other things:
1. I can not write the file in one shot, as the files are 250MB in size. I can not allocate 250MB to write to a file, there is just not enough ram.
2. We've found FAT32 wholly unsuitable for big partitions (120GB and up). FAT32 does not even format reliably on these big partitions.
Cheers
OD
|
|
|
|
|
I've got an MFC based database application (built with VS.NET 2002) with a login feature. I want to detect if the user hasn't interacted with the app for a certain timeout period. When I detect this "event", I want to either exit the application, OR lock-out the user and force them to type in a password again.
I can handle the code for a timer handler to check flags, and do the exit or login.
But how to detect keypresses/mouse movement? I want to avoid rewrites to each of my dialogs and main app. Is there a way to hook into the app's message queue and detect keypresses and mouse activity for all child windows? Or any other simple way?
TIA,
Andrew
|
|
|
|
|
I did this with an application wide keyboard and mouse hook. Let me see if I can dig up the code.
class CActivity
{
public:
CActivity();
virtual ~CActivity();
public:
static DWORD GetLastActivity();
static void SetLastActivity(DWORD dwActivity);
public:
static DWORD m_dwLastActivity;
static HANDLE m_hMutex;
};
extern CActivity g_Activity;
template<BYTE nID>
class CInactivityHook
{
public:
CInactivityHook();
virtual ~CInactivityHook();
public:
BOOL Start(DWORD dwThreadID);
BOOL Stop();
protected:
static LRESULT CALLBACK MyKeyHookFunc(int code, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MyMouHookFunc(int code, WPARAM wParam, LPARAM lParam);
protected:
static HHOOK m_hMyKeyHook;
static HHOOK m_hMyMouseHook;
};
template<BYTE nID>
HHOOK CInactivityHook<nID>::m_hMyKeyHook=NULL;
template<BYTE nID>
HHOOK CInactivityHook<nID>::m_hMyMouseHook=NULL;
template<BYTE nID>
CInactivityHook<nID>::CInactivityHook()
{
g_Activity.SetLastActivity(::GetCurrentTime());
m_hMyKeyHook=0;
m_hMyMouseHook=0;
}
template<BYTE nID>
CInactivityHook<nID>::~CInactivityHook()
{
Stop();
}
template<BYTE nID>
CInactivityHook<nID>::Stop()
{
if ( m_hMyKeyHook) {
UnhookWindowsHookEx( m_hMyKeyHook );
m_hMyKeyHook = NULL;
}
if ( m_hMyMouseHook) {
UnhookWindowsHookEx( m_hMyMouseHook );
m_hMyMouseHook = NULL;
}
return TRUE;
}
template<BYTE nID>
CInactivityHook<nID>::Start(DWORD dwThreadID)
{
if ( !m_hMyKeyHook) {
m_hMyKeyHook= SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)MyKeyHookFunc, AfxGetInstanceHandle(),
(DWORD)dwThreadID);
}
if ( !m_hMyMouseHook) {
m_hMyMouseHook= SetWindowsHookEx(WH_MOUSE, (HOOKPROC)MyMouHookFunc, AfxGetInstanceHandle(),
(DWORD)dwThreadID);
}
return TRUE;
}
template<BYTE nID>
LRESULT CALLBACK CInactivityHook<nID>::MyKeyHookFunc(int code, WPARAM wParam, LPARAM lParam)
{
CActivity::SetLastActivity(::GetCurrentTime());
return CallNextHookEx( m_hMyKeyHook, code, wParam, lParam);
}
template<BYTE nID>
LRESULT CALLBACK CInactivityHook<nID>::MyMouHookFunc(int code, WPARAM wParam, LPARAM lParam)
{
CActivity::SetLastActivity(::GetCurrentTime());
return CallNextHookEx( m_hMyMouseHook, code, wParam, lParam);
}
///////
// now in my cview
CInactivityHook<0> CommonViewInactivity;
void CCommonView::EnableInactivityHook( BOOL fEnable )
{
CommonViewInactivity.Start(::GetCurrentThreadId());
SetTimer(DONE_DIGITIZING_TIMER,1000,NULL);
CActivity::SetLastActivity(::GetCurrentTime());
}
void CCommonView::OnTimer(UINT nIDEvent)
{
if ( nIDEvent == DONE_DIGITIZING_TIMER) {
// calculate difference between current time and time stored in CActivity::GetLastActivity();
}
}
John
|
|
|
|
|
Think about writing an article for it
Ryan "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"
|
|
|
|
|
Thanks. I have very little free time at the moment...
John
|
|
|
|
|
(maybe not the right wording )
(porting from C to C++)
I have a few enum lying around in the global namespace, I was wondering how can I qualify them ?
for example I have a line style enum that I want to "qualify" for example instead of just writing
myline->style = dashed;
I would like something like
myline->style = LineStyle::dashed;
What's the best way ?
Thanks.
Maximilien Lincourt
"Never underestimate the bandwidth of a station wagon filled with backup tapes." ("Computer Networks" by Andrew S Tannenbaum )
|
|
|
|
|
How is dashed defined?
Like this?
enum { dashed = 0, solid = 1};
Cause I believe you can do something like:
enum LineStyle { dashed = 0, solid = 1};
myline->style = LineStyle::dashed;
-Nathan
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
Nathan Blomquist wrote:
enum LineStyle { dashed = 0, solid = 1};
myline->style = LineStyle::dashed;
Unfortunately that doesn't work.
This does though:
struct LineStyle
{
enum {
dashed = 0,
solid
};
};
|
|
|
|
|
Or you could put it in a namespace as below:
namespace LineStyle
{
enum {dashed = 0,solid};
};
I prefer to qualify it because most times the name is not unique enough that I will worry about a clash.
John
|
|
|
|
|
Yes, namespacewould be more appropriate for this task than using struct. I've never been in the habit of using the namespace keyword; its existence slipped my mind. I may have to start using it...
|
|
|
|
|
Nathan Blomquist wrote:
enum LineStyle { dashed = 0, solid = 1};
Yes, but I get compilation errors
enum LineStyleType
{
NoStyle = -1,
Center = 0,
Dot,
Dash,
MaxLineStyle
};
curve->style = LineStyleType::Dot;
D:\mmb\ver300\build_IT\mbConstructLine.cpp(613) : error C2039: 'Dot' : is not a member of 'LineStyleType'<br />
../lib\include/coreconst.h(266) : see declaration of 'LineStyleType'
Thanks.
Maximilien Lincourt
"Never underestimate the bandwidth of a station wagon filled with backup tapes." ("Computer Networks" by Andrew S Tannenbaum )
|
|
|
|
|
That's because the scope resolution operator - :: - is not used to dereference into an instance type. You can either use a namespace or (more appropriately) define the enum as static.
Cheers,
Tom Archer
Inside C#, Extending MFC Applications with the .NET Framework
It's better to listen to others than to speak, because I already know what I'm going to say anyway. - friend of Jörgen Sigvardsson
|
|
|
|
|
Cool thanks... Always good to be corrected and informed.
Thanks,
Nathan
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
|
make the enum static
static enum LineStyle { ... }
regards
modified 12-Sep-18 21:01pm.
|
|
|
|