switch over to 64-bit timekeeping

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@1455 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-12-20 08:32:01 +00:00
parent 34580c58e3
commit b41a033217
5 changed files with 105 additions and 60 deletions

View File

@ -84,8 +84,8 @@
* String ::== size (char)^size *
* size ::== int *
* Date ::== seconds nanoseconds *
* seconds ::== unsigned 32 bit int *
* nanoseconds ::== unsigned 32 bit int *
* seconds ::== signed 64 bit int *
* nanoseconds ::== signed 32 bit int *
\********************************************************************/
#include <fcntl.h>
@ -110,7 +110,7 @@
#define PERMS 0666
#define WFLAGS (O_WRONLY | O_CREAT | O_TRUNC)
#define RFLAGS O_RDONLY
#define VERSION 8
#define VERSION 9
/* hack alert the current file format does not support most of the
@ -146,7 +146,7 @@ static Transaction *readTransaction( int fd, Account *, int token );
static Split *readSplit( int fd, int token );
static char *readString( int fd, int token );
static time_t readDMYDate( int fd, int token );
static int readTSDate( int fd, struct timespec *, int token );
static int readTSDate( int fd, Timespec *, int token );
static int writeAccountGroupToFile( char *datafile, AccountGroup *grp );
static int writeGroup( int fd, AccountGroup *grp );
@ -154,7 +154,7 @@ static int writeAccount( int fd, Account *account );
static int writeTransaction( int fd, Transaction *trans );
static int writeSplit( int fd, Split *split);
static int writeString( int fd, char *str );
static int writeTSDate( int fd, struct timespec *);
static int writeTSDate( int fd, Timespec *);
/*******************************************************/
/* backwards compatibility definitions for numeric value
@ -230,15 +230,33 @@ double xaccFlipDouble (double val)
return u.d;
}
long long xaccFlipLongLong (long long val)
{
union {
unsigned int i[2];
long long d;
} u;
unsigned int w0, w1;
u.d = val;
w0 = xaccFlipInt (u.i[0]);
w1 = xaccFlipInt (u.i[1]);
u.i[0] = w1;
u.i[1] = w0;
return u.d;
}
/* if we are running on a little-endian system, we need to
* do some endian flipping, because the xacc native data
* format is big-endian */
* format is big-endian. In particular, Intel x86 is little-endian. */
#ifndef WORDS_BIGENDIAN
#define XACC_FLIP_DOUBLE(x) { (x) = xaccFlipDouble (x); }
#define XACC_FLIP_LONG_LONG(x) { (x) = xaccFlipLongLong (x); }
#define XACC_FLIP_INT(x) { (x) = xaccFlipInt (x); }
#define XACC_FLIP_SHORT(x) { (x) = xaccFlipShort (x); }
#else
#define XACC_FLIP_DOUBLE(x)
#define XACC_FLIP_LONG_LONG(x)
#define XACC_FLIP_INT(x)
#define XACC_FLIP_SHORT(x)
#endif /* WORDS_BIGENDIAN */
@ -673,7 +691,7 @@ readTransaction( int fd, Account *acc, int token )
xaccTransSetDateSecs (trans, secs);
xaccTransSetDateEnteredSecs (trans, secs);
} else {
struct timespec ts;
Timespec ts;
int rc;
/* read posted date first ... */
@ -1011,9 +1029,9 @@ readSplit ( int fd, int token )
}
xaccSplitSetReconcile (split, recn);
/* version 8 and newwer files store date-reconciled */
/* version 8 and newer files store date-reconciled */
if (8 <= token) {
struct timespec ts;
Timespec ts;
int rc;
rc = readTSDate( fd, &ts, token );
@ -1124,20 +1142,37 @@ readString( int fd, int token )
* Return: the Date struct *
\********************************************************************/
static int
readTSDate( int fd, struct timespec *ts, int token )
readTSDate( int fd, Timespec *ts, int token )
{
int err=0;
unsigned int secs, nsecs;
long long int secs = 0; /* 64-bit int */
long int nsecs = 0;
err = read( fd, &secs, sizeof(unsigned int) );
if( err != sizeof(unsigned int) )
/* secs is a 32-bit in in version 8 & earlier files,
* and goes 64-bit in the later files */
if (8 >= token)
{
return -1;
long int sicks;
err = read( fd, &sicks, sizeof(long int) );
if( err != sizeof(long int) )
{
return -1;
}
XACC_FLIP_INT (sicks);
secs = sicks;
}
else
{
err = read( fd, &secs, sizeof(long long int) );
if( err != sizeof(long long int) )
{
return -1;
}
XACC_FLIP_LONG_LONG (secs);
}
XACC_FLIP_INT (secs);
err = read( fd, &nsecs, sizeof(unsigned int) );
if( err != sizeof(unsigned int) )
err = read( fd, &nsecs, sizeof(long int) );
if( err != sizeof(long int) )
{
return -1;
}
@ -1511,7 +1546,7 @@ writeTransaction( int fd, Transaction *trans )
Split *s;
int err=0;
int i=0;
struct timespec ts;
Timespec ts;
ENTER ("writeTransaction");
/* If we've already written this transaction, don't write
@ -1570,7 +1605,7 @@ writeSplit ( int fd, Split *split )
{
int err=0;
int acc_id;
struct timespec ts;
Timespec ts;
double damount;
Account *xfer_acc = NULL;
char recn;
@ -1663,21 +1698,22 @@ writeString( int fd, char *str )
* Return: -1 on failure *
\********************************************************************/
static int
writeTSDate( int fd, struct timespec *ts)
writeTSDate( int fd, Timespec *ts)
{
int err=0;
unsigned int tmp;
int tmp;
long long ltmp;
/* write 32 bits to file format, even if time_t is 64 bits */
tmp = ts->tv_sec;
XACC_FLIP_INT (tmp);
err = write( fd, &tmp, sizeof(unsigned int) );
if( err != sizeof(int) )
/* write 64 bits to file format */
ltmp = ts->tv_sec;
XACC_FLIP_LONG_LONG (ltmp);
err = write( fd, &tmp, sizeof(long long int) );
if( err != sizeof(long long int) )
return -1;
tmp = ts->tv_nsec;
XACC_FLIP_INT (tmp);
err = write( fd, &tmp, sizeof(unsigned int) );
err = write( fd, &tmp, sizeof(int) );
if( err != sizeof(int) )
return -1;

View File

@ -79,6 +79,8 @@ xaccMallocQuery (void)
static int Sort_DATE_NUM_AMOUNT (Split **, Split **);
#define LONG_LONG_MAX 0x7fffffffffffffffLL
void
xaccInitQuery (Query *q)
{
@ -89,23 +91,17 @@ xaccInitQuery (Query *q)
q->changed = 0;
q->max_num_splits = INT_MAX ;
q->earliest.tv_sec = 0;
q->earliest.tv_sec = - (LONG_LONG_MAX) - 1;
q->earliest.tv_nsec = 0;
/* hack alert HACK ALERT Y2K problem -- danger danger.
* For some stupid reason, struct Timespec uses long int
* instead of time_t for seconds. This means we will have
* overflow in year 2004 which is stupid, and needs to be
* fixed.
*/
/* q->latest.tv_sec = ULONG_MAX; */
q->latest.tv_sec = LONG_MAX;
/* Its a signed, 64-bit int */
q->latest.tv_sec = LONG_LONG_MAX;
q->latest.tv_nsec = 0;
q->earliest_found.tv_sec = LONG_MAX;
q->earliest_found.tv_sec = LONG_LONG_MAX;
q->earliest_found.tv_nsec = 0;
q->latest_found.tv_sec = 0;
q->latest_found.tv_sec = - (LONG_LONG_MAX) - 1;
q->latest_found.tv_nsec = 0;
q->sort_func = (int (*)(const void*, const void *)) Sort_DATE_NUM_AMOUNT;

View File

@ -892,8 +892,11 @@ xaccTransCommitEdit (Transaction *trans)
(trans->orig->date_posted.tv_sec != trans->date_posted.tv_sec))
{
DEBUG ("xaccTransCommitEdit(): date changed to %lu %s\n",
trans->date_posted.tv_sec, ctime (&trans->date_posted.tv_sec));
DEBUGCMD ({
time_t sicko = trans->date_posted.tv_sec;
DEBUG ("xaccTransCommitEdit(): date changed to %Lu %s\n",
trans->date_posted.tv_sec, ctime (&sicko));
})
/* since the date has changed, we need to be careful to
* make sure all associated splits are in proper order
* in thier accounts. The easiest way of ensuring this
@ -1443,7 +1446,7 @@ xaccTransSetDateSecs (Transaction *trans, time_t secs)
if (!trans) return;
CHECK_OPEN (trans);
PINFO ("xaccTransSetDateSecs(): addr=%p set date to %lu %s \n",
trans, secs, ctime (&secs));
trans, secs, ctime (&secs));
trans->date_posted.tv_sec = secs;
trans->date_posted.tv_nsec = 0;
@ -1469,19 +1472,22 @@ xaccTransSetDateEnteredSecs (Transaction *trans, time_t secs)
}
void
xaccTransSetDateTS (Transaction *trans, struct timespec *ts)
xaccTransSetDateTS (Transaction *trans, Timespec *ts)
{
if (!trans) return;
CHECK_OPEN (trans);
PINFO ("xaccTransSetDateTS(): addr=%p set date to %lu %s \n",
trans, ts->tv_sec, ctime (&ts->tv_sec));
DEBUGCMD ({
time_t sicko = ts->tv_sec;
PINFO ("xaccTransSetDateTS(): addr=%p set date to %Lu %s \n",
trans, ts->tv_sec, ctime (&sicko));
})
trans->date_posted.tv_sec = ts->tv_sec;
trans->date_posted.tv_nsec = ts->tv_nsec;
}
void
xaccTransSetDateEnteredTS (Transaction *trans, struct timespec *ts)
xaccTransSetDateEnteredTS (Transaction *trans, Timespec *ts)
{
if (!trans) return;
CHECK_OPEN (trans);
@ -1740,7 +1746,7 @@ xaccSplitSetDateReconciledSecs (Split *split, time_t secs)
}
void
xaccSplitSetDateReconciledTS (Split *split, struct timespec *ts)
xaccSplitSetDateReconciledTS (Split *split, Timespec *ts)
{
if (!split) return;
MARK_SPLIT (split);

View File

@ -54,6 +54,20 @@ typedef struct _account_group AccountGroup;
typedef struct _split Split;
typedef struct _transaction Transaction;
/* struct timespec64 is just like timespec except that we use
* a 64-bit signed int to store the seconds. This should adequetely
* cover dates in the distant future as well as the distant past, as long
* as they're not more than a couple dozen times the age of the universe.
* Note that both gcc and the IBM Toronto xlC compiler (aka CSet,
* VisualAge, etc) correctly handle long long as a 64 bit quantity,
* even on the 32-bit Intel x86 and PowerPC architectures. I'm assuming
* that all the other modern compilers are clean on this issue too ...
*/
struct timespec64 {
long long int tv_sec;
long int tv_nsec;
};
typedef struct timespec64 Timespec;
/** PROTOTYPES ******************************************************/
/*
@ -115,7 +129,7 @@ void xaccTransRollbackEdit (Transaction *);
* xaccTransSetDateSecs(), but takes a convenient day-month-year format.
*
* The xaccTransSetDateTS() method does the same thing as
* xaccTransSetDateSecs(), but takes a struct timespec.
* xaccTransSetDateSecs(), but takes a struct timespec64.
*
* The xaccTransSetDateToday() method does the same thing as
* xaccTransSetDateSecs(), but sets the date to the current system
@ -124,10 +138,10 @@ void xaccTransRollbackEdit (Transaction *);
void xaccTransSetDate (Transaction *, int day, int mon, int year);
void xaccTransSetDateSecs (Transaction *, time_t);
void xaccTransSetDateToday (Transaction *);
void xaccTransSetDateTS (Transaction *, struct timespec *);
void xaccTransSetDateTS (Transaction *, Timespec *);
void xaccTransSetDateEnteredSecs (Transaction *, time_t);
void xaccTransSetDateEnteredTS (Transaction *, struct timespec *);
void xaccTransSetDateEnteredTS (Transaction *, Timespec *);
/* set the Num and Description fields ... */
@ -188,8 +202,8 @@ char * xaccTransGetNum (Transaction *);
char * xaccTransGetDescription (Transaction *);
char * xaccTransGetDocref (Transaction *);
time_t xaccTransGetDate (Transaction *);
void xaccTransGetDateTS (Transaction *, struct timespec *);
void xaccTransGetDateEnteredTS (Transaction *, struct timespec *);
void xaccTransGetDateTS (Transaction *, Timespec *);
void xaccTransGetDateEnteredTS (Transaction *, Timespec *);
/* return the number of splits */
int xaccTransCountSplits (Transaction *trans);
@ -260,8 +274,8 @@ void xaccSplitSetDocref (Split *, const char *);
*/
void xaccSplitSetReconcile (Split *, char);
void xaccSplitSetDateReconciledSecs (Split *, time_t);
void xaccSplitSetDateReconciledTS (Split *, struct timespec *);
void xaccSplitGetDateReconciledTS (Split *, struct timespec *);
void xaccSplitSetDateReconciledTS (Split *, Timespec *);
void xaccSplitGetDateReconciledTS (Split *, Timespec *);
/*

View File

@ -50,13 +50,6 @@
#include "config.h"
#include "Transaction.h" /* for typedefs */
/* Major-League Hack Alert -- bit Y2K problem: struct timespec seems
* to have declared tv_sec to be a signed long, not an unsigned long.
* This majorly hoses in the year 2004, as date comparisons suddenly
* fail because the seconds value will go negative.
*/
typedef struct timespec Timespec;
/** STRUCTS *********************************************************/
/*
* Double-entry is forced by having at least two splits in every