-saveDocument: and package problems
-
Hi,
I've had a couple of reports of serious data loss in my app and am stumped. I'm wondering if anyone here might have any ideas; perhaps I have made a bad assumption somewhere.
My app uses a package format to save its data - a regular folder (but with an extension and icon, obviously) containing a bunch of RTFD files (the text documents that can be opened by my app) and a saved dictionary file containing a structured list of these files for the source list.
I open the package using NSDocument's - readFromURL:ofType:error:. In this method I just look for the dictionary file and get information from that, and load into the editor the text file that was last opened (well, this is vastly simplified, but this is the main gist).
To save the package, I've overridden NSDocument's -saveDocument:. It doesn't call super's method at all - all it does is write any text files that have been marked as changed into the project package as RTFD files and saves the project dictionary file.
In the past month, I've had two different users report a data loss issue to me. In both cases, it seems that their computer has gone into a deep sleep with my app open. Upon coming out of sleep - I'm not sure at which point here as the users have been vague, but I would imagine after they have closed and reopened the project - everything inside the package has been wiped except for the RTFD file that corresponds with the text document that is open in the text view. I'm not sure if the deep sleep has anything to do with it or is just a coincidence.
I should add that my app auto-saves on a delayed timer, so that -saveDocument: gets called after a few seconds of inactivity (any key-press or mouse movement delays the save until two seconds of inactivity have passed), but I don't think that has any effect here.
I've checked all my calls to NSFileManager's -removeFileAtPath:handler: and various calls to -writeToFile:... to see if anything could be accidentally replacing the project directory and there is nothing in my code that could be explicitly wiping these files; in the affected projects, there are files that get wiped that are never even touched after the initial project creation (for instance, the file version info file).
Is there anything in the system that I have described that would be leaving my app open to such data loss? The app has thousands of users and this has only ever been reported by two or three users, but when it comes to data loss I don't want to assume that it is just a fault with their machines or something odd that they have done. Both recent users have swore that they have done nothing odd to the file - they haven't moved it, synchronised it or anything else.
If anyone has any ideas about what might cause this sort of thing, I'd be very grateful to hear them. I know the above isn't much to go on, but there really is nothing else at play in my app that could wipe data.
Many thanks in advance and all the best,
Keith
____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ -
I don't know why your users are losing data but I do know that in
deep sleep, NSTimers do not fire (I think because NSRunLoops stop.)
You will likely want to do something on wake from deep sleep. To do
that:
//set up notification for awake from sleep
[[[NSWorkspace sharedWorkspace] notificationCenter]
addObserver:self
selector:@selector(didAwakeFromSleep)
name:NSWorkspaceDidWakeNotification
object:nil];
- (void)didAwakeFromSleep
{
//delay so that there's time to re-establish internet connection
after wake if that is needed
[self performSelector:@selector(doSomeKindOfUpdate)
withObject:nil
afterDelay:DELAY_AFTER_WAKE_FROM_SLEEP];
}
James
On Feb 19, 2008, at 9:37 AM, Keith Blount wrote:> Message: 11
> Date: Tue, 19 Feb 2008 09:28:00 -0800 (PST)
> From: Keith Blount <keithblount...>
> Subject: -saveDocument: and pamailto:<keithblount...>
> problems
> To: <cocoa-dev...>
> Message-ID: <296747.42019.qm...>
> Content-Type: text/plain; charset=us-ascii
>
> Hi,
>
> I've had a couple of reports of serious data loss in my app and am
> stumped. I'm wondering if anyone here might have any ideas; perhaps
> I have made a bad assumption somewhere.
>
> My app uses a package format to save its data - a regular folder
> (but with an extension and icon, obviously) containing a bunch of
> RTFD files (the text documents that can be opened by my app) and a
> saved dictionary file containing a structured list of these files
> for the source list.
>
> I open the package using NSDocument's - readFromURL:ofType:error:.
> In this method I just look for the dictionary file and get
> information from that, and load into the editor the text file that
> was last opened (well, this is vastly simplified, but this is the
> main gist).
>
> To save the package, I've overridden NSDocument's -saveDocument:.
> It doesn't call super's method at all - all it does is write any
> text files that have been marked as changed into the project
> package as RTFD files and saves the project dictionary file.
>
> In the past month, I've had two different users report a data loss
> issue to me. In both cases, it seems that their computer has gone
> into a deep sleep with my app open. Upon coming out of sleep - I'm
> not sure at which point here as the users have been vague, but I
> would imagine after they have closed and reopened the project -
> everything inside the package has been wiped except for the RTFD
> file that corresponds with the text document that is open in the
> text view. I'm not sure if the deep sleep has anything to do with
> it or is just a coincidence.
>
> I should add that my app auto-saves on a delayed timer, so that -
> saveDocument: gets called after a few seconds of inactivity (any
> key-press or mouse movement delays the save until two seconds of
> inactivity have passed), but I don't think that has any effect here.
>
> I've checked all my calls to NSFileManager's -
> removeFileAtPath:handler: and various calls to -writeToFile:... to
> see if anything could be accidentally replacing the project
> directory and there is nothing in my code that could be explicitly
> wiping these files; in the affected projects, there are files that
> get wiped that are never even touched after the initial project
> creation (for instance, the file version info file).
>
> Is there anything in the system that I have described that would be
> leaving my app open to such data loss? The app has thousands of
> users and this has only ever been reported by two or three users,
> but when it comes to data loss I don't want to assume that it is
> just a fault with their machines or something odd that they have
> done. Both recent users have swore that they have done nothing odd
> to the file - they haven't moved it, synchronised it or anything else.
>
> If anyone has any ideas about what might cause this sort of thing,
> I'd be very grateful to hear them. I know the above isn't much to
> go on, but there really is nothing else at play in my app that
> could wipe data.
>
> Many thanks in advance and all the best,
> Keith -
Hi James, many thanks for your replies, much appreciated. Actually, I'm not too worried about the auto-save, as that isn't the problem with data loss. Even if auto-save fails during a sleep, the user can manually save and auto-save will kick in again as soon as they start using the app provided the project has an internal -hasChanges flag set.
More investigation seems to indicate that somehow, an empty project folder is being created that wipes out the existing project folder. So, anything that is open in the app - the current text document and the source list - get saved into the empty project that has just wiped out the full one. I reproduced this by creating a folder in the Finder with the same name as my project file and then replacing the project file whilst it was open. This had exactly the same effect as the sort of data loss my users have reported.
The trouble is, I don't know why this would happen other than the user choosing to do it. The obvious answer would be something in my code - an erroneous call to -createDirectoryAtPath:handler: or writeToFile:..., accidentally passing in the project path instead of the subpath, but I've been through my code and can't find anything that would do this.
Given that I've overridden -saveDocument:, I can't imagine there being anywhere else (internal to NSDocument) that could save an empty package over the file path, but I could be wrong... Weird.
Thanks again and all the best,
Keith
____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile. Try it now. http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ -
> To save the package, I've overridden NSDocument's -saveDocument:. It
> doesn't call super's method at all - all it does is write any text
> files that have been marked as changed into the project package as
> RTFD files and saves the project dictionary file.
Is there any reason youâre not using -fileWrapperOfType:error: and
letting the document machinery handle things for you?
-Ben -
Yes, because that would require returning an NSFileWrapper built from all of the documents in the project, meaning that potentially hundreds of files would get written to disk. So I override -saveDocument: so that I can write only what's necessary and have complete control. (Likewise, I used to use -readFromFileWrapper:... until I realised that that loaded the whole project directory to memory - meaning that hundreds of megabytes could be loaded up - when all I needed was a few internal files, so I went with -readFromURL:... instead).
Thanks for your reply.
All the best,
Keith
----- Original Message ----
From: Benjamin Stiglitz <stig...>
To: Keith Blount <keithblount...>
Cc: <cocoa-dev...>
Sent: Wednesday, February 20, 2008 3:30:31 PM
Subject: Re: -saveDocument: and package problems>To
save
the
package,
I've
overridden
NSDocument's
-saveDocument:.
It>doesn't
call
super's
method
at
all
-
all
it
does
is
write
any
text>files
that
have
been
marked
as
changed
into
the
project
package
as>RTFD
files
and
saves
the
project
dictionary
file.
Is
there
any
reason
youââ¬â¢re
not
using
-fileWrapperOfType:error:
and
letting
the
document
machinery
handle
things
for
you?
-Ben
____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page.
http://www.yahoo.com/r/hs


