Closed Bug 180154 Opened 22 years ago Closed 14 years ago

freeze nsISeekableStream

Categories

(Core :: XPCOM, defect, P3)

defect

Tracking

()

RESOLVED WONTFIX
Future

People

(Reporter: darin.moz, Unassigned)

References

()

Details

(Keywords: arch, embed)

Attachments

(3 files, 3 obsolete files)

embedders, consumers of nsIUploadChannel probably need a way to rewind streams. personally, i'm happy with the interface as is. we'd need to beef it out with some documentation. specifically, it should be made clear that |setEOF| may be unimplemented or otherwise generate an error (e.g., can only truncate a writable stream).
Attached file nsISeekableStream.idl draft (deleted) —
/* * Sets the stream pointer to the size of the stream plus the value * of the offset parameter. */ Should that say "minus"? I'm not sure why one would want to position the pointer past the end....
Er, nevermind. That's obviously supposed to take a negative offset.... still a little confusing, but...
Should this interface use some kind of typedef for the file offsets rather than fixing it at PRUint32. Just thinking ahead when we have gigabit internet throughput and people are browsing multi-gigabyte HTML pages ;-) Realistically though I've started seeing downloads that are greater than 1gig. So this may not be that far off.
void seek(in long whence, in long offset); PRUint32 tell(); Should the return value type of tell maybe be the same as the type of the offset argument of seek?
Oh yeah, and fwiw I agree with dbradley... Can we make this simply use a 64 bit type? NSPR has functions for such file accesses, at least Linux supports such files, and files are getting larger and larger, so I don't think we should freeze the 32 bits into an interface. Also note that nsIFile uses: 212 attribute PRInt64 fileSize; http://lxr.mozilla.org/seamonkey/source/xpcom/io/nsIFile.idl#212 (I wonder why it's signed...)
the reset of necko is 32 bit. we don't directly support long long buffers/offsets. David - the whence bits are a direct mapping of NSPR constants. NSPR hasn't added any in years, why would we? I will fix up the PRInt32 --> long thing.
>David - the whence bits are a direct mapping of NSPR constants. NSPR hasn't >added any in years, why would we? Not sure what you mean here. I was only talking about the size of the "offset" and how 2gigs seemed like a rather small limit for this interface.
david, ignore that part of the comment. Basically my point was that the 32bit offset is consistent with the rest of Necko APIs.
see: nsIStreamListener::OnDataAvailable(..., PRUint32 offset, PRUint32 count) nsIInputStream::Available(PRUint32 *result) nsIChannel::GetContentLength(PRInt32 *result) these are all frozen interfaces. we'd also need to rev these interfaces if we cared about supporting >2G files. should support for >2G files really be a requirement right now?
IMO we should serious consider support of downloading files >2gigs, but I don't know if these interfaces are involved or not. While even with broadband this can take a while, I'm sure we'll see people swaping large files, game demos, mpegs, etc.
this would be a pretty big overhaul of necko. I just created the tracking bug 184452.
Damn, what the hell was I thinking. I apologize for being a dumbass – too preoccupied with the rumor mill.
i'm ok with freezing this interface. i do have a couple nits though... - NS_SEEK_SET ... it's unfortunate that we have to have this NS_ prefix. any clever ideas of how we could eliminate that? - |const PRInt32| should probably be |const long| to match the type of |whence|. otherwise, i think this interface is a good one to freeze. (i'm also a little concerned about the fact that some of our implementations only implement Tell. this is one of those interfaces where a reference to the interface is not really an indication of what functionality is really available. maybe that's an implementation bug.)
> any clever ideas of how we could eliminate that? Why not just rename the constants? We'll have to change some implementations, but....
but to what? SEEK_SET is #define'd by most operating systems. suppose the OS values are not compatible with the NSPR values, which these are based on? so, any suggestions?
Ah. Didn't realize we had a name collision... No bright ideas offhand (GK_SEEK_SET is just as bad as NS_SEEK_SET).
We could just use the OS values if they exist, couldn't we? People shouldn't be hardcoding constants, and since c+ modules would have to be recompiled on a new os, theres no compat issue, is there? Although that may be expsing more of the internals than we want to.
bbaetz: you're trusting that the NSPR constants map directly to the OS constants. i don't know if that is a safe thing to assume. cc'ing wtc for advice. we could also just #undef SEEK_SET, etc. above the interface decl. that would only cause minor pain for those who need to #include both our header file and the stdc header file(s). this might be worth the hassle.
Well, thats what I meant about perhaps exposing the interface too much. This is just a wrapper arround fseek though, and so the constants' meanings are fairly standard. Then you'd only have an issue where an os defined SEEK_SET and made it mean something else But yeah, it probably isn't a good idea to reuse those constants. We could #undef them first, I suppose, but then people couldn't use themin teh same file, and so on. |static const int|, perhaps?
You can't assume that the NSPR constants map directly to the OS constants.
Why the setEOF()? I mean the rest of the interface (and the name) implies read-only access to the stream.. would there be any difference between calling close() on the actual stream? It wouldn't surprise me if there was.. I just find it odd to see it in this interface, it seems like it belongs somewhere else.
alec: SetEOF means truncate at the current offset. This follows the windows convention of seek then set eof to truncate at a location in the stream. SetEOF is not at all equivalent to Close.
I think the issue is, that nsISeekableStream denotes read only access to the file. So finding a method that would actually modify the file seems a little out of place. I could have sworn I saw this same discussion somewhere, but wasn't able to locate it.
well, i guess we can move it to a different interface. maybe one that inherits from nsISeekableStream? the issue is that we don't want to make it so awkward to seek and truncate.
however, i just realized (and confirmed via LXR) that after my changes for bug 176919, nsISeekableStream::setEOF is never called. (NOTE: nsFileTransport.cpp is the only caller, but that code is dead and needs to be CVS removed.) so, perhaps the solution is simple. perhaps we might want to just eliminate SetEOF. now, it is of course a useful function in many cases, but if we aren't using it now, then maybe there is not good reason to freeze an interface which provides it.
This is the start of one discussion on setEOF http://bugzilla.mozilla.org/show_bug.cgi?id=86474#c32 I don't think it's the one I was thinking of, though.
darin agreed to own xpcom.io.
Assignee: dougt → darin
Status: NEW → ASSIGNED
Priority: -- → P3
Target Milestone: --- → mozilla1.4beta
seek and truncate seems fine, I just know there are lots of consumers and implementors of input streams where you don't want to be modifying the underlying stream.. i.e. whereas seeking and reading are commonly paired and require two distinct interfaces, seeking and truncating is (I would assume) used much less often so I see no reason to make a seeking interface overly complex to make that particular pairing..
Target Milestone: mozilla1.4beta → mozilla1.5alpha
Target Milestone: mozilla1.5alpha → Future
mailnews needs at least the ability to use the full 32 bits of file size, so we can have files up to 4GB, instead of being limited to 2GB. (Seek taking a signed instead of an unsigned is the issue there). Having 64 bit files in mailnews would be a whole new chunk of work...one possibility is having a new SEEK type which treats the offset as an unsigned int, instead of treating negative numbers as a reverse seek, something like NS_SEEK_CUR_UNSIGNED. Obviously, this is ugly and non-standard, but on the plus side, it might allow us to go from 2GB->4GB pretty easily.
why not use PRInt64 for seek types? mailnews wouldn't need to switch entirely to 64 bit functions, it could just convert an unsigned long to a PRInt64 when it wants to call Seek..
well, hows about this. We have a seekForward() and seekBackwards() (or seek() and rewind()), each of which take a long long - then we can still support 4G. It also syntacically defines defines two semantically different actions. I doubt there is ever a time that someone is going to want to seek an arbitrary amount forward or backward without knowing if they want to go forward or backward in the first place. Furthermore, we could make a nsIRewindableStream that contains the rewind() call, so that streams could indicate this capability to rewind via QI response.
converting mailnews is not a big issue, since we're not using nsISeekableStream much, if at all. We'd like to get rid of nsFileSpec and use nsISeekableStream and nsFileStream, but we'd like to get around the 2GB limit. I was more worried about the uses of nsISeekableStream in the rest of the tree and converting those to a 64 bit interface.
Verbose naming and a "rewindable" interface just makes the API story ulgier. I vote for either adding a nsISekableStream64 or fixing up the nsISeekableStream to take 64 bit value. I prefer the former.
A new 64 bit interface would seem the easiest way to introduce it to the code base without affecting the existing code. If we're unsure of the impact of 64 bit ints in the existing interfac,e going that route would be most prudent. If "we're" comfortable with the impact it would be great to convert the existing interface, and open up the ability to handle large files/streams throughout the app.
Darin and I were talking about this a bit - it seems like the least intrusive fix in terms of the rest of the code would be to add seek64 and tell64 methods to nsISeekableStream, since it's not a frozen interface, and Darin wants to remove setEOF anyway. Adding a new nsISeekableStream64 interface would add a bit of vtable bloat and make the client code QI for the new interface. Converting nsISeekableStream to 64 bit methods is probably not prohibitively difficult. From lxr, it looks like there are around 15-20 different files that use nsISeekableStream::seek, and many of them are seeking to the beginning of the stream anyway. I can try either of these. I just need some sort of consensus and buyin...
if there are that few callers, I say just update the interface and them - I would hope the pattern would be pretty straight forward.. we've done much more extensive changes in the past :)
I'd probably be more concerned about tell than seek, since it's likely to have more of ripple effect. I only see a handle full of those, but they're doing things like storing the result out into data members, which would have to be changed, and anything that touches those. That still may not be a big deal given the small number of references to tell I saw on lxr, but I didn't walk more than the top level So there could be one instance that fans out to many things that in turn fan out into many more things.
Attached patch crude patch that builds and runs (obsolete) (deleted) — Splinter Review
This patch builds and runs with 64 bit seek and tell - it's crude, and for the most part, just treats the 64 bit result of tell as a 32 bit value. It also doesn't use our 64 bit int macros, which Darin says might still be used in embedding environments. I'm going to look at nsInt64 and see if I should be using that...but, this patch does allow mail files to be > 2GB. I think most of the users of nsISeekableStream will still end up just using the 32 bits, like fastLoad, which isn't going to need files > 2GB, and is storing offsets in the data file as 32 bit numbers anyway. And the StringStream class probably doesn't need to worry about strings > 2GB...Anyway, this is the work in progress.
Does anyone else have input about the 64bit math? Does nsInt64 do the right thing on platforms that don't support 64 bit ints directly? I'd like to see what progress I can make on driving this forward.
Blocks: 207400
> Does nsInt64 do the right thing on platforms that don't support 64 bit ints directly? nsInt64 should work correctly on all platforms, even those that do not natively support 64-bit integer types.
Attached patch non-mail part of patch, using nsInt64 (obsolete) (deleted) — Splinter Review
this patch addresses Darin's comment about wrapping 64 bit operations with nsInt64. I've separated out the mailnews diffs into a different patch.
Attachment #139776 - Attachment is obsolete: true
Mailnews part of patch. I had to stop using nsMsgKeySet for the new msg set because it doesn't like id's > 0x7fffffff. nsMsgKeyArray will take up more memory but it does simplify the code a bit. In normal situations, there won't be a lot of new messages, so I don't think it's a big deal.
Attachment #143825 - Flags: review?(darin)
Comment on attachment 143825 [details] [diff] [review] non-mail part of patch, using nsInt64 >Index: xpcom/io/nsISeekableStream.idl >+ void seek(in long whence, in long long offset); >+ unsigned long long tell(); hmm... i think it might make more sense for tell() to return a signed long long instead. it seems to me that you should be able to seek to any position indicated by tell. also, the lseek system call uses signed integers for both the current stream position and the new stream position. PR_Seek64 behaves just like lseek. if you make tell return signed long long then you avoid the casting from PRUint64 to PRInt64. that casting worried me anyways since it means we really don't support the full range of PRUint64. i think this change might simplify the patch considerably. nit: i noticed some off-by-one character indentation problems, especially in member variable declarations.
Attachment #143825 - Flags: review?(darin) → review-
sure, I can do that - I was just following the existing behaviour of making tell return an unsigned value. I wasn't happy about the casts either...
(In reply to comment #46) > sure, I can do that - I was just following the existing behaviour of making tell > return an unsigned value. I wasn't happy about the casts either... yeah, i figured that was the case. i hadn't given this much thought until looking at your patch and seeing what a pain all those casts are.
this does remove all the casts - I can't say it makes the patch much simpler, but there aren't any more casts to PRInt64. I've also made nsStorageStream just do 32 bit streams - if we want to make that support larger streams, we can do that orthogonally...
Attachment #143825 - Attachment is obsolete: true
Comment on attachment 144054 [details] [diff] [review] patch addressing Darin's comments - non-mail diffs only >Index: netwerk/base/src/nsInputStreamPump.cpp >+ nsInt64 offsetBefore64 = offsetBefore; >+ nsInt64 offsetAfter64 = offsetAfter; >+ if (offsetAfter64 > offsetBefore64) >+ mStreamOffset += (PRInt32) (offsetAfter64 - offsetBefore64); nit: maybe add an assertion that the difference fits in a PRInt32? not that that isn't going to always be the case ... ;-) >Index: xpcom/io/nsFastLoadFile.cpp >+ NS_ASSERTION(fileSize < 0xFFFFFFFF, "fileSize must fit in 32 bits"); >+ // todo - assert fileSize fits in 32 bits; maybe this "todo" is bogus now? also, do you need to use LL_ macros of nsInt64 inside this NS_ASSERTION? >+ PRInt64 footerOffset; >+ rv = seekable->Tell(&footerOffset); >+ >+ mHeader.mFooterOffset = (PRUint32) footerOffset; this cast needs to use LL_ macros? >+ PRInt64 fileSize; >+ rv = seekable->Tell(&fileSize); >+ mHeader.mFileSize = (PRUint32) fileSize; same here. >Index: xpcom/io/nsStringStream.cpp >+ NS_ASSERTION(offset < 0xFFFFFFFF, "string streams only support 32 bit offsets"); use LL_ macros to compare or use nsInt64? >Index: xpcom/obsolete/nsFileStream.h >+ PRInt64 result = -1; use LL_ macros? >Index: xpcom/obsolete/nsIFileStream.cpp >+ case NS_SEEK_SET: ; break; semicolon before break should not be needed. >+ nsInt64 zero = LL_Zero(); maybe just do: nsInt64 zero = 0; r=darin with these nits picked.
Attachment #144054 - Flags: review+
this addresses Darin's comments, assuming I haven't missed anything :-)
Attachment #144054 - Attachment is obsolete: true
Attachment #144227 - Flags: superreview?(mscott)
Comment on attachment 143826 [details] [diff] [review] handle local folders > 2GB and < 4GB (checked in) corresponding mailnews changes
Attachment #143826 - Flags: superreview?(mscott)
Minor nit if you think of it before you check it in, the minus1 declarations could benefit from adding "const". There were a few other places (fileSize64,maxUint32, etc.) where, I assume for conversion reasons, you assign and never change the value, those could use const as well. Most smart compilers would probably figure it out.
Attachment #144227 - Flags: superreview?(mscott) → superreview+
Attachment #143826 - Flags: superreview?(mscott) → superreview+
One more thing that needs to change: The IID of nsISeekableStream must be changed. See bug 239038, and a comment I posted to super-reviewers@mozilla.org
I went ahead and bumped the interface IID: Checking in nsISeekableStream.idl; /cvsroot/mozilla/xpcom/io/nsISeekableStream.idl,v <-- nsISeekableStream.idl new revision: 3.9; previous revision: 3.8 done It appears that the latest patch landed earlier today.
Blocks: 242583
Blocks: 242591
Attachment #143826 - Attachment description: handle local folders > 2GB and < 4GB → handle local folders > 2GB and < 4GB (checked in)
Attachment #144227 - Attachment description: patch addressing Darin's last comments - non-mail diffs only → patch addressing Darin's last comments - non-mail diffs only (checked in)
Blocks: 268520
QA Contact: scc → xpcom
Assignee: darin → nobody
Status: ASSIGNED → NEW
We no longer freeze interfaces.
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: