Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Close all open DBFs and reopen

130 views
Skip to first unread message

Martin

unread,
May 2, 2012, 7:37:50 AM5/2/12
to
Hello

I want to close all of the files in use, then reopen them in the same
workareas and server instances, how easy is this to do?

Karl Faller

unread,
May 2, 2012, 8:27:14 AM5/2/12
to
Martin,
firstly, i think there's some mismatch - "same workareas" vs "same
server instance". The DBServer handles the WA behind the scenes, and
there's NO guarantee to get any special WA "number" assigned.

Any case, to reopen you have to remember "what", so there has to be
some "registry" where you do the bookkeeping- a protect of the shell
might be a good place.
The actual closing/reopen should be trivial...

Karl

Stephen Quinn

unread,
May 2, 2012, 12:02:39 PM5/2/12
to
Martin

> I want to close all of the files in use, then reopen them in the same
> workareas and server instances, how easy is this to do?

To open them in the same workareas you'd need to track the order in which
they we opened in the first place. IIRC dbservers are allocated from the top
down and Clipper style USE command are opened bottom up (or vice versa, it's
in the help somewhere) (there are 1024 work areas available)

If your servers are attached to windows then you'll need to close them as
well.

You won't get the same instances as once the object is destroyed (ie when
you close it) it's gone, never to see the light of day again<g>

So it begs the question - why do you want to do this??

CYA
Steve


Stephen Quinn

unread,
May 2, 2012, 12:09:39 PM5/2/12
to
Karl

> firstly, i think there's some mismatch - "same workareas" vs "same
> server instance". The DBServer handles the WA behind the scenes, and
> there's NO guarantee to get any special WA "number" assigned.

I think you'll find that the WA is assigned consecutively 0 ->1023 (or
1023->0) when using servers.
It's the ALIAS that is guaranteed to be UNIQUE for all open dbservers.

CYA
Steve


D.J.W. van Kooten

unread,
May 2, 2012, 1:56:49 PM5/2/12
to
On Wed, 02 May 2012 14:27:14 +0200, Karl Faller
<k.faller_w...@onlinehome.de> wrote:

Hello Martin,
>
>Any case, to reopen you have to remember "what", so there has to be
>some "registry" where you do the bookkeeping- a protect of the shell
>might be a good place.
>The actual closing/reopen should be trivial...
>
As Karl said, this is the way to do. A word of warning, you may come
across DBCloseAll() doing the job too, on first sight. Don't use it!
It will totally disrupt your program; after reopening databases all
kind of unpredictable errors will occur.

This is how we do it:

FUNCTION CloseOpenDB
LOCAL ni AS DWORD
LOCAL oThisServer AS OBJECT
FOR ni:=1 UPTO ALen(IC2GetAppObject():aFilesOpened)
oThisServer:=IC2GetAppObject():aFilesOpened[ni]
IF oThisServer # NULL_OBJECT .AND. oThisServer:Used
oThisServer:Close()
oThisServer := NULL_OBJECT
ENDIF
NEXT
RETURN TRUE


where:

FUNCTION IC2GetAppObject()
//#s Returns application object and thus gives access to 'global'
variables from any place
RETURN GetAppObject()

Of course, anny opening/closing of databases requires you to add this
in IC2GetAppObject():aFilesOpened.

Dick

Karl Faller

unread,
May 2, 2012, 5:47:07 PM5/2/12
to
Steve,
>> firstly, i think there's some mismatch - "same workareas" vs "same
>> server instance". The DBServer handles the WA behind the scenes, and
>> there's NO guarantee to get any special WA "number" assigned.
>
>I think you'll find that the WA is assigned consecutively 0 ->1023 (or
>1023->0) when using servers.
Yes.
(BTW, in VN it is 4095, caused me some head scratching why my "list
WAs in use" func stopped working after transportation ;-)

But exactly _which_ number you get for any given server instance
depends on the amount of other used WAs. So i wanted to suggest
avoiding this mismatch - either work on WA numbers, OR with DBServer
instances, but not both, and certainly not to close and
reopen/recreate - this calls for dragons...

HAND
Karl

Mathias

unread,
May 3, 2012, 1:21:26 AM5/3/12
to
Hello Martin,

In my application I close the server objects, copy the files to a zip-fil, and opens them again, without the user noticing anything more than a short time (half a second) with the hourglass. The trick is to do a SuspendNotification first. If you don't you loose the columns. After saving the files, the server objects are recreated, correct sort order and active record is set and after that I do a simple Use on the datawindow. The user may have several project windows opened. This is hadled by keeping av array of all opened project windows. Before save the "PreSave" method is called in all opened windows and after PostSave is called. In PreSave the active record number and the filter is stored. In PostSave these properties are set again and Use is called.

/Mathias

Martin

unread,
May 3, 2012, 5:01:14 AM5/3/12
to
Thanks all I will have a nose through

It is so a database update can be done without quitting the application,
but file has to be closed then reopened to use the new file format.
Planning to send a message from the updating program to tell the other
users to do a close open.

But more excited about the pack while in shared mode.

Mathias

unread,
May 4, 2012, 3:20:52 AM5/4/12
to
Sorry if my post was misleading. The files that I pack are used exclusively used by one user. Infact the zip file is an estimation project file with a special suffix so that users don't open it as a zip. The project file is unpacked in a temporary directory and are used by one user only.

What I wanted to do was to give you some clues to how you can close the databases and open them again without disturbing the user too much, even if the user is browsing data in a databrowser or datawindow.

If you want to make a backup while the files are used you have to use shadow copy. I haven't done this myself, but I'm using Coban backup (www.cobiansoft.com) for my own purposes and this freeware backup product can backup files that are currently being used.

/Mathias

richard.townsendrose

unread,
May 4, 2012, 8:21:16 AM5/4/12
to
Martin

see ADS11 .. you can now restructure, pack, reindex WITHOUT closing
table let alone zapping users

also for code to gather work areas and tables see Lib 11 FloatWin

richard

METHOD UpdateWArea() CLASS FloatWin
LOCAL wCtr AS DWORD
LOCAL cAlias AS STRING
LOCAL aWorkAreas AS ARRAY
LOCAL wNoTables:=0 AS DWORD

aWorkAreas:={}

FOR wCtr:=1024 DOWNTO 1

cAlias := ALIAS( wCtr )
IF ! cAlias == NULL_STRING
wNoTables:=wNoTables + 1
AAdd(aWorkAreas, AllTrim(cAlias) + ' - ' + NTrim(wCtr))
ENDIF

NEXT

SELF:oDCSystemServers:FillUsing(aWorkAreas)

SELF:oDCNoTables:Value:=NTrim(wNoTables)

RETURN NIL

Martin

unread,
May 4, 2012, 9:10:12 AM5/4/12
to
Restructure not so good, need to close open and indexes are not
changeable, so that is unlikely for now.

Pack - just need to skip or similar

Martin

unread,
May 4, 2012, 9:10:34 AM5/4/12
to
We would be packing in shared mode!

Stephen Quinn

unread,
May 4, 2012, 10:45:10 AM5/4/12
to
Martin

> We would be packing in shared mode!
Impossible - you should read the docs about PACK.

The only way to 'pack' while the DBF is open SHARED is to
COPY STRUCTURE TO NEWDBF
USE NEWDBF NEW EXCLUSIVE
GOTOP
DO WHILE ! EOF
// Write to NEW DBF
ENDDO

CLOSE ALL // You'll lose all connections to windows & stuff
here
DELETE OLDDBF
RENAME NEWDBF TO OLDDBF
RE-CREATE THE INDICES
// Try to re-attach to windows etc...

Use a slightly different syntax for DBServers<g>

CYA
Steve


dlzc

unread,
May 4, 2012, 12:24:16 PM5/4/12
to
Dear Martin:

On Thursday, May 3, 2012 2:01:14 AM UTC-7, Martin wrote:
> Thanks all I will have a nose through
>
> It is so a database update can be done without
> quitting the application, but file has to be
> closed then reopened to use the new file format.
> Planning to send a message from the updating
> program to tell the other users to do a close
> open.
>
> But more excited about the pack while in shared mode.

You could be even more excited, if instead of blindly adding new records, you search for deleted records first, and re-used those that did not still have locks on them. Then packing becomes unnecessary.
http://www.ghservices.com/gregh/clipper/trix0006.htm

Obviously, this would be best handled in your own function for this purpose.

David A. Smith

Stephen Quinn

unread,
May 4, 2012, 1:15:39 PM5/4/12
to
Martin

"dlzc" <dl...@cox.net> wrote in message
news:5078709.1251.1336148657030.JavaMail.geo-discussion-forums@ynmk20...
> You could be even more excited, if instead of blindly adding new records,
> you search for deleted records first, and re-used those that did not still
> have locks on them. Then packing becomes unnecessary.
> http://www.ghservices.com/gregh/clipper/trix0006.htm
>
> Obviously, this would be best handled in your own function for this
> purpose.

Override the Append() method in a sub-class of DBServer.
Eg
- sample method with litte or no error checking<g>

METHOD Append() CLASS MyDBServer

// Save the current order

SELF:Suspendnotification()

// I used to have an index TAG called '_DEL' for deleted() records for
// those DBFs where I recycled records
// eg - INDEX ON FLD1 TAG '_DEL' FOR DELETED()
SELF:SetOrder( '_DEL' )

// Check if any deleted records are available
IF SELF:OrderKeyCount() > 0
// Get the first available
SELF:GoTop()
SELF:Recall()
SELF:BlankAllTheFieldDataThatMayBeThereFromTheOldRecord()
ELSE
// No deleted() records available so normal append to the end of the
DBF
SUPER:Append()
ENDIF

// Get the recno before notifications are reset
nRecNo := SELF:RecNo
SELF:ResetNotification()

// Put old order back & make sure we're still on the recalled/new record
SELF:Goto( nRecNo )
RETURN

CYA
Steve


D.J.W. van Kooten

unread,
May 6, 2012, 5:00:44 PM5/6/12
to
On Fri, 4 May 2012 09:24:16 -0700 (PDT), dlzc <dl...@cox.net> wrote:

Hello David,

>You could be even more excited, if instead of blindly adding new records, you search for deleted records first, and re-used those that did not still have locks on them. Then packing becomes unnecessary.
>
That's also an option of ADS, when using their native format. I do not
like this option however. Having the records in natural order equal to
the order of addition, and being able to access deleted records for a
while (until they are really packed) can help a lot in solving
problems.

When using such a feature, you would need to do a lot of extra work
before having the same 'check options'. And the advantage may be
little; some databases may even see more deletions than additions when
you introduce the feature and are still left with deleted records
which may need packing at some point.

Dick

dlzc

unread,
May 6, 2012, 6:38:43 PM5/6/12
to
Dear D. J. W. van Kooten:

On Sunday, May 6, 2012 2:00:44 PM UTC-7, D. J. W. van Kooten wrote:
> On Fri, 4 May 2012 09:24:16 -0700 (PDT), dlzc <dl***@cox.net> wrote:
>
> Hello David,
>
> > You could be even more excited, if instead of
> > blindly adding new records, you search for
> > deleted records first, and re-used those that
> > did not still have locks on them. Then packing
> > becomes unnecessary.
>
> That's also an option of ADS, when using their
> native format. I do not like this option however.
> Having the records in natural order equal to the
> order of addition, and being able to access
> deleted records for a while (until they are
> really packed) can help a lot in solving problems.

You can achieve the same effect, by issuing a serial number to each record as it is added, and reuse records with the smallest / oldest serial number first.

> When using such a feature, you would need to
> do a lot of extra work before having the same
> 'check options'. And the advantage may be little;
> some databases may even see more deletions than
> additions when you introduce the feature and are
> still left with deleted records which may need
> packing at some point.

Agreed. The OP however is describing a problem, wherein packing becomes necessary. So this probably will not affect his case.

Additionally, is there a guarantee that when packed, the remaining undeleted records are in the order they were added? I can imagine rolling records down from the end of the file to fill in spaces for deleted records, as a means to speed the operation up.

David A. Smith

Stephen Quinn

unread,
May 6, 2012, 9:57:01 PM5/6/12
to
David

> Additionally, is there a guarantee that when packed, the remaining
> undeleted records are in the order they > were added? I can imagine
> rolling records down from the end of the file to fill in spaces for
> deleted
> records, as a means to speed the operation up.

A pack is done sequentially start of file to end of file.

Pack moves the first non-deleted record (found after any deleted record)
into the space left by the first deleted record.
Eg
DBF with 20 records, 5,10,15 are deleted
1 - Find 1st deleted (5) drop a marker
2 - Find next non-deleted record (6)
3 - Copy non-deleted (6) back to deleted (5) (etc...) - move marker to new
position (6)
Repeat until you find the next deleted record (rec 7-9)
Repeat to eof

I wrote about this in the Clipper ng in the early/mid 90s and someone
(forget who<g>) tested it by packing a DBF on an almost full floppy disk (so
it would fail mid-pack and the record order could be seen with a hex editor)

The above is why you cannot PACK in shared mode - you don't want anyone
writing to records that are no longer located in the same place as when you
read them.

CYA
Steve


Martin

unread,
May 8, 2012, 9:04:54 AM5/8/12
to
ADS say it is so I will be trying as soon as we have the V11 Beta

Client-less access to Advantage data through the Advantage Web
Platform OData web service. Now you can easily access data from mobile
devices, tablets, Macintosh, or any device, on any platform, with any
modern development environment

Online table maintenance capabilities that allow you to maintain
Advantage data like never before; all while users are actively accessing
the tables.

Updated and new clients
New utilities
SQL enhancements
Performance enhancements
and much more


On 04/05/2012 15:45, Stephen Quinn wrote:
> Martin
>
>> We would be packing in shared mode!
> Impossible - you should read the docs about PACK.
>
> The only way to 'pack' while the DBF is open SHARED is to
> COPY STRUCTURE TO NEWDBF
> USE NEWDBF NEW EXCLUSIVE
> GOTOP
> DO WHILE ! EOF
> // Write to NEW DBF
> ENDDO
>
> CLOSE ALL // You'll lose all connections to windows& stuff

Martin

unread,
May 8, 2012, 9:06:37 AM5/8/12
to
I have been record recycling for over 20 years.

But blank indexes get slow, and shrinking a file in size after an
archive is good

Martin

unread,
May 8, 2012, 9:08:54 AM5/8/12
to
I am pretty sure it uses transaction management for this

On 07/05/2012 02:57, Stephen Quinn wrote:
> David

Karl Wochele

unread,
May 8, 2012, 9:28:53 AM5/8/12
to
Hi Martin,

yes, blank indexes get slow. So don't use any...

We use Str(recno(),10,0) as index-expression .and. deleted() as
condition for our recycling-index..

Karl
0 new messages