#include foxpro.h *#define DEBUG_MODE lparameters tcArg1 * throttle memory usage =sys(3050, 1, 256 * 1024) && foreground =sys(3050, 2, 256 * 1024) && background * Run flag public glRun glRun = .t. on shutdown do trapShutdown with glRun #ifndef DEBUG_MODE on escape glRun = .f. * we don't want a screen Application.Visible = .F. #endif goPaths = newobject("drpaths", "drpaths") with goPaths goBaseRegs = newobject("drbasereg", "baseregisters", null, .TablePath) declare APIGetBlock in (.RootPath + "server.dll") as GetBlock string @ lpszBuf declare integer APIGetBufferSize in (.RootPath + "server.dll") as GetBufferSize declare integer APIGetTimeStamp in (.RootPath + "server.dll") as GetTimeStamp string @ lpszBuf declare Sleep in Win32API as Sleep integer dwMilliseconds endwith local lcBuffer, lnTimeStamp, lnLastTimeStamp local lcTrendPath lcTrendPath = goPaths.TrendPath local lnTickInterval, lnSleepInterval, lnTickSpan, lnBufferSize lnTickInterval = 1 && in seconds *lnTickInterval = goBaseRegs.TickInterval && in seconds lnSleepInterval = 500 && in milliseconds lnTickSpan = 2*24*60*60 && in seconds *lnTickSpan = goBaseRegs.TickSpan && in seconds lnBufferSize = GetBufferSize() local lnAnalogCount, lnAnalogOffset, lnSegmentCount, lnCapacity, lnRemainder lnAnalogCount = goBaseRegs.AnalogTransferMax lnAnalogOffset = 2 * goBaseRegs.AnalogOffset + 1 && times two because count is in words, && add one because it is zero based lnSegmentCount = int(lnAnalogCount / 127) lnRemainder = lnAnalogCount % 127 lnRemainder = iif(lnRemainder = 0, 127, lnRemainder) lnCapacity = int((lnSegmentCount + 1) * lnTickSpan / lnTickInterval) + 1 local llErrorFlag llErrorFlag = .t. && hack a try/catch do while llErrorFlag loTickTable = newobject("stTick", "logtable", null, lcTrendPath) if vartype(tcArg1) = 'C' and upper(alltrim(tcArg1)) = "PACK" loTickTable.PackOnOpen = .t. loTickTable.IndexOnOpen = .t. endif loTickTable.CreateOnFileNotFoundError = .t. loTickTable.OpenTable() if isexclusive() && an error occurred, try again loTickTable.PackOnOpen = .f. loTickTable.IndexOnOpen = .f. loTickTable.OpenTable() endif llErrorFlag = .f. && we hope for success on error do trapError with llErrorFlag set order to time_seg on error if llErrorFlag use tcArg1 = "PACK" && an error occured, so we force a pack endif enddo * set the buffer mode set multilocks on cursorsetprop(Buffering, DB_BUFLOCKRECORD) * locate the file type ID record locate for count = 255 if !found() * create a new file type ID record, segment holds the ID * 0 = Log, 1 = Snapshot, 2 = On Demand insert into Tick (time, segment, count, value) ; values (0, 0, 255, "Log File") endif * trim table size if necessary if reccount() > lnCapacity locate for count != 255 delete next reccount() - lnCapacity loTickTable.CloseTable() loTickTable.OpenTable() endif lcBuffer = space(lnBufferSize) lnLastTimeStamp = 0 do while glRun lnTimeStamp = GetTimeStamp(0) if lnTimeStamp >= lnLastTimeStamp + lnTickInterval GetBlock(@lcBuffer) lnTimeStamp = GetTimeStamp(@lcBuffer) lnLastTimeStamp = lnTimeStamp * * Tick Log * for i = 0 to lnSegmentCount if reccount() < lnCapacity insert into Tick (time, segment, count, value) ; values (lnTimeStamp, i, iif(i = lnSegmentCount, lnRemainder, 127), ; substr(lcBuffer, lnAnalogOffset + (i * 254), 254)) else locate for count != 255 replace time with lnTimeStamp, segment with i, ; count with iif(i = lnSegmentCount, lnRemainder, 127), ; value with substr(lcBuffer, lnAnalogOffset + (i * 254), 254) endif endfor llErrorFlag = .f. && we hope for success on error do trapError with llErrorFlag * Commit changes tableupdate(2, .t.) on error if llErrorFlag *test * wait window trans(lntimestamp) endif flush && force write of buffered data to disk else sleep(lnSleepInterval) endif doevents enddo procedure trapError lParameter tlErrorFlag tlErrorFlag = .t. && an error occured return && continue execution on the next line endproc procedure trapShutdown * throw away any uncommited changes if !empty(alias()) =tablerevert(.t.) endif on shutdown quit endproc