C stat() and daylight savings - c++

I'm having serious trouble with the function stat(). I have an application compiled under cygwin ond Windows 7 and the same app compiled with MSVC++ on Windows 7. The app contains the following code:
struct stat stb;
memset( &stb, 0, sizeof( stb ) );
stat( szPath, &stb );
cout << hex << uppercase << setw(8) << stb.st_mtime << endl;
szPath is a path to a file. The file does not get modified in any way by the app. The problem is, that i get different results for some files. For example:
cygwin version: 40216D72
MSVC++ version: 40217B82
The difference is always E10 = 3600 = 1 hour
By using google, i found this, which seems to be exactly the same issue i'm seeing. Is there a portable way how to fix this? I cannot use any WinAPI calls. The most simple and reliable solution is what i'm looking for, but if it needs to be complicated, so be it. Reliability and portability (win + linux) is the most important thing here.

To obtain both reliability and portability here (or in most situations of this sort where two platforms do different things with what should be the "same" code), you will probably need to use some form of target-dependent code, like:
#ifdef _MSC_VER
// do MSVC++-specific code
#else
// do Linux/Cygwin/generic code
#endif
You then ought to be able to use WinAPI calls in the _MSC_VER section, because that will only be compiled when you're using MSVC++

Apparently per http://support.microsoft.com/kb/190315 this is actually a FEATURE although it really seems like a bug to me. They say you can work around it by clearing "Automatically adjust clock for daylight saving changes" in the Date/Time Properties dialog box for the system clock.
If you have the date of the file, you can use the relative state of dst to determine if you need to make a one-hour adjustment yourself in MSVC only, but that's hacky as well.

Not sure about the functions you are using but I do know that Windows and Linux use the system clock differently. Windows stores local time (including DST) on the system clock. Linux (at least traditionally) stores GMT (or UTC to be precise) on the system clock. I don't if this applies to cygwin.
If a linux system shares hardware with windows it needs to be configured to use the system clock like windows or get messed-up every time windows adjusts DST.

Related

How to retrieve total system CPU usage from Windows in C++?

I need to retrieve total CPU usage on the fly for a feedback system to change the behavior based on whether CPU is getting throttled or not. For this, I looked into NtQuerySystemInformation sys call which provides system information at any given time but it seems like this function has been deprecated in the latest versions of Windows since MSDN page says
[NtQuerySystemInformation may be altered or unavailable in future
versions of Windows. Applications should use the alternate functions
listed in this topic.]
Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
Does anyone know what OS versions this call is supported on? Win 7/8/8.1/10? Is there any other way to directly retrieve total CPU usage?
Officaially, there are two functions are in the MSDN.
GetSystemTimes(): It looks more easier but posted a long time ago.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724400(v=vs.85).aspx
GetSystemInfo() : I've got the sample code from https://code.msdn.microsoft.com/windowsdesktop/Use-PerformanceCounter-to-272d57a1
DWORD GetProcessorCount()
{
SYSTEM_INFO sysinfo;
DWORD dwNumberOfProcessors;
GetSystemInfo(&sysinfo);
dwNumberOfProcessors = sysinfo.dwNumberOfProcessors;
return dwNumberOfProcessors;
}
vector<PCTSTR> GetValidCounterNames()
{
vector<PCTSTR> validCounterNames;
DWORD dwNumberOfProcessors = GetProcessorCount();
DWORD index;
vector<PCTSTR> vszProcessNames;
TCHAR * szCounterName;
validCounterNames.push_back(TEXT("\\Processor(_Total)\\% Processor Time"));
validCounterNames.push_back(TEXT("\\Processor(_Total)\\% Idle Time"));
// skip some codes
return validCounterNames;
}
Good Luck !
In my opinion, Windows command "tasklist /v " will show the CPU TIME and MEMORY from the OS and you can call the command through 'system' or other functions.
PS. I still think looking at the OS side is the best way for monitoring CPU usage. (If I use the function, it will also do the same thing inside.)

Vista and FindFirstFileEx(..., FIND_FIRST_EX_LARGE_FETCH)

i have an application that queries a specific folder for its contents with a quick interval. Up to the moment i was using FindFirstFile but even by applying search pattern i feel there will be performance problems in the future since the folder can get pretty big; in fact it's not in my hand to restrict it at all.
Then i decided to give FindFirstFileEx a chance, in combination with some tips from this question.
My exact call is the following:
const char* search_path = "somepath/*.*";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFileEx(search_path, FindExInfoBasic, &fd, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);
Now i get pretty good performance but what about compatibility? My application requires Windows Vista+ but given the following, regarding FIND_FIRST_EX_LARGE_FETCH:
This value is not supported until Windows Server 2008 R2 and Windows 7.
I can pretty much compile it on my Windows 7 but what will happens if someone runs this on a Vista machine? Does the function downgrade to a 0
(default) in this case? It's safe to not test against operating system?
UPDATE:
I said above about feeling the performance is not good. In fact my numbers are following on a fixed set of files (about 100 of them):
FindFirstFile -> 22 ms
FindFirstFile -> 4 ms (using specific pattern; however all files may wanted)
FindFirstFileEx -> 1 ms (no matter patterns or full list)
What i feel about is what will happen if folder grows say 50k files? that's about x500 bigger and still not big enough. This is about 11 seconds for an application querying on 25 fps (it's graphical)
Just tested under WinXP (compiled under win7). You'll get 0x57 (The parameter is incorrect) when it calls ::FindFirstFileEx() with FIND_FIRST_EX_LARGE_FETCH. You should check windows version and dynamically choose the value of additional parameter.
Also FindExInfoBasic is not supported before Windows Server 2008 R2 and Windows 7. You'll also get run-time 0x57 error due to this value. It must be changed to another alternative if binary is run under old windows version.
at first periodic queries a specific folder for its contents with a quick interval - not the best solution I think.
you need call ReadDirectoryChangesW - as result you will be not need do periodic queries but got notifies when files changed in directory. the best way bind directory handle with BindIoCompletionCallback or CreateThreadpoolIo and call first time direct call ReadDirectoryChangesW. then when will be changes - you callback will be automatic called and after you process data - call ReadDirectoryChangesW again from callback - until you got STATUS_NOTIFY_CLEANUP (in case BindIoCompletionCallback) or ERROR_NOTIFY_CLEANUP (in case CreateThreadpoolIo) in callback (this mean you close directory handle for stop notify) or some error.
after this (first call to ReadDirectoryChangesW ) you need call FindFirstFileEx/FindNextFile loop but only once - and handle all returned files as FILE_ACTION_ADDED notify
and about performance and compatibility.
all this is only as information. not recommended to use or not use
if you need this look to - ZwQueryDirectoryFile - this give you very big win performance
you only once need open File handle, but not every time like with
FindFirstFileEx
but main - look to ReturnSingleEntry parameter. this is key
point - you need set it to FALSE and pass large enough buffer to
FileInformation. if set ReturnSingleEntry to TRUE function
and return only one file per call. so if folder containing N files -
you will be need call ZwQueryDirectoryFile N times. but with
ReturnSingleEntry == FALSE you can got all files in single call, if buffer will be large enough. in all case you serious reduce
the number of round trips to the kernel, which is very costly
operation . 1 query with N files returned much more faster than N
queries. the FIND_FIRST_EX_LARGE_FETCH and do this - set
ReturnSingleEntry to TRUE - but in current implementation (i check this on latest win 10) system do this only in
FindNextFile calls, but in first call to
FindFirstFileEx it (by unknown reason) still use
ReturnSingleEntry == TRUE - so will be how minimum 2 calls to the ZwQueryDirectoryFile, when possible have single call
(if buffer will be large enough of course) and if direct use
ZwQueryDirectoryFile - you control buffer size. you can
allocate once say 1MB for buffer, and then use it in periodic
queries. (without reallocation). how large buffer use
FindFirstFileEx with FIND_FIRST_EX_LARGE_FETCH - you can
not control (in current implementation this is 64kb - quite
reasonable value)
you have much more reach choice for FileInformationClass - less
informative info class - less data size, faster function worked.
about compatibility? this exist and worked from how minimum win2000 to latest win10 with all functional. (in documentation - "Available starting with Windows XP", however in ntifs.h it declared as #if (NTDDI_VERSION >= NTDDI_WIN2K) and it really was already in win2000 - but no matter- XP support more than enough now)
but this is undocumented, unsupported, only for kernel mode, no lib file.. ?
documented - as you can see, this is both for user and kernel mode - how you think - how is FindFirstFile[Ex] / FindNextFile - working ? it call ZwQueryDirectoryFile - no another way. all calls to kernel only through ntdll.dll - this is fundamental. ( yes still possible that ntdll.dll stop export by name and begin export by ordinal only for show what is unsupported really was). lib file exist, even two ntdll.lib and ntdllp.lib (here more api compare first) in any WDK. headers, where declared ? #include <ntifs.h>. but it conflict with #include <windows.h> - yes conflict, but if include ntifs.h in namespace with some tricks - possible avoid conflicts

Conversion of timespec for Windows 7 VS 2010

I am trying to build OpenVDB viewer for Windows 7 and bumped into this line of code:
secs = fabs(secs);
int isecs = int(secs);
struct timespec sleepTime = { isecs /*sec*/, int(1.0e9 * (secs - isecs)) /*nsec*/ };
nanosleep(&sleepTime, /*remainingTime=*/NULL);
Unfortunately, i dont know what exactly is the meaning of this code as i need to make it VS2010 compiler compatible in order to build it.
So, can i know what is the equivalent of this code or some other library that i can use to edit it easily??
Assuming secs is a float value giving the time the thread shall sleep in seconds, such as e.g.
float secs = 0.8312f;
You can replace that for the windows version with:
float secs = 0.8312f;
DWORD delay = static_cast<DWORD>(fabs(secs * 1000.0f));
Sleep(delay);
Possibly you could add some checks to this (such as if secs is not negative...).
In order to keep the main code base portable, you could create an extra module where you define your own portable sleep function, maybe with the signature void PortableSleep(float seconds);. Then, place in one .cpp file the Unix implementation, in another the win32 implementation and link accordingly.
What you also can do is using std::this_thread::sleep_for() if you like to waste time on figuring out how the <chrono> stuff works (VS lacks one feature, which makes it a bit harder to use).

Why does ICU's Locale::getDefault() return "root"?

Using the ICU library with C++ I'm doing:
char const *lang = Locale::getDefault().getLanguage();
If I write a small test program and run it on my Mac system, I get en for lang. However, inside a larger group project I'm working on, I get root. Anybody have any idea why? I did find this:
http://userguide.icu-project.org/locale/resources
so my guess is that, when running under the larger system, some ICU resources aren't being found, but I don't know what resources, why they're not being found, or how to fix it.
Additional Information
/usr/bin/locale returns:
LANG="en_US.ISO8859-1"
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL="C"
If I write a small C program:
char const *lang = setlocale( LC_ALL, "" ):
I get en_US.ISO8859-1.
OS: Mac OS X 10.6.4 (Snow Leopard)
ICU version: 4.3.4 (latest available via MacPorts).
A little help? Thanks.
root is surely an odd default locale - you don't see many native root-speakers these days.
But seriously, is it safe to assume on the larger system that someone hasn't called one of the variants of setDefault("root")?
What does something like /usr/bin/locale return on this system (if you can run that)?
ICU 4.4 now has a test program called 'icuinfo', does it also return root as the default locale?
What OS/platform is this on, and which version of ICU?

How to get the current time zone?

In most of the examples I had seen:
time_zone_ptr zone( new posix_time_zone("MST-07") );
But I just want to get the current time zone for the machine that runs the code. I do not want to hard code the time zone name.
Plain posix: call tzset, use tzname.
#include <ctime>
tzset();
time_zone_ptr zone(new posix_time_zone(tzname[localtime(0)->tm_isdst]));
Posix with glibc/bsd additions:
time_zone_ptr zone(new posix_time_zone(localtime(0)->tm_zone));
The above are abbreviated Posix timezones, defined in terms of offset from UTC and not stable over time (there's a longer form that can include DST transitions, but not political and historical transitions).
ICU is portable and has logic for retrieving the system timezone as an Olson timezone (snippet by sumwale):
// Link with LDLIBS=`pkg-config icu-i18n --libs`
#include <unicode/timezone.h>
#include <iostream>
using namespace U_ICU_NAMESPACE;
int main() {
TimeZone* tz = TimeZone::createDefault();
UnicodeString us;
std::string s;
tz->getID(us);
us.toUTF8String(s);
std::cout << "Current timezone ID: " << s << '\n';
delete tz;
}
On Linux, ICU is implemented to be compatible with tzset and looks at TZ and /etc/localtime, which on recent Linux systems is specced to be a symlink containing the Olson identifier (here's the history). See uprv_tzname for implementation details.
Boost doesn't know how to use the Olson identifier. You could build a posix_time_zone using the non-DST and DST offsets, but at this point, it's best to keep using the ICU implementation. See this Boost FAQ.
Quite late in the day, but I was looking for something similar so this can hopefully help others. The following (non-boost) way using strftime seems to work on most platforms:
time_t ts = 0;
struct tm t;
char buf[16];
::localtime_r(&ts, &t);
::strftime(buf, sizeof(buf), "%z", &t);
std::cout << "Current timezone: " << buf << std::endl;
::strftime(buf, sizeof(buf), "%Z", &t);
std::cout << "Current timezone: " << buf << std::endl;
Or one can use std::time_put for a pure C++ version.
Well, maybe you could do it using the GeoIP library. I know it's a bit of an overkill, but since most computers in the world are connected to the internet, you could probably get away with it. According to the guy I'm developing for, it's been over 99% accurate.
Note: This is a dumb idea. I am just stretching for answers.
In order to properly answer this question, it's important to understand that the time zone support in Boost is severely limited.
It's primarily focused on POSIX time zones, which have several limitations. These limitations are discussed in the POSIX section of the timezone tag wiki, so I won't repeat them here.
It has functions that work with IDs of IANA/Olson time zones, but it artificially maps these to POSIX values - which has the effect of flattening the time zone to a single point in history. These mappings are stored in a csv file in the Boost source code.
The csv file hasn't been updated since April 2011, and there have been many changes to time zones since then. So, the mappings it does have are somewhat inaccurate.
In general, I would not recommend Boost for working with time zones. Instead, consider the ICU TimeZone Classes, which are part of the ICU project. You will find these to be fully portable, and they have full and correct time zone support.
It's worth mentioning that ICU is used in many popular applications. For example, the Google Chrome web browser gets it's time zone support from ICU.
In ICU, the current local system time zone is available as the default time zone. You can read more in the section "Factory Methods and the Default Timezone" in the ICU documentation.
You could always try getting the universal time and local time from boost and checking the difference, it's probably full of caveats though.