Back to index

lightning-sunbird  0.9+nobinonly
nsCacheEntryDescriptor.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is nsCacheEntryDescriptor.cpp, released
00017  * February 22, 2001.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 2001
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Gordon Sheridan, 22-February-2001
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsICache.h"
00042 #include "nsCache.h"
00043 #include "nsCacheService.h"
00044 #include "nsCacheEntryDescriptor.h"
00045 #include "nsCacheEntry.h"
00046 #include "nsReadableUtils.h"
00047 #include "nsIOutputStream.h"
00048 #include "nsCRT.h"
00049 #include "nsAutoLock.h"
00050 
00051 NS_IMPL_THREADSAFE_ISUPPORTS2(nsCacheEntryDescriptor,
00052                               nsICacheEntryDescriptor,
00053                               nsICacheEntryInfo)
00054 
00055 nsCacheEntryDescriptor::nsCacheEntryDescriptor(nsCacheEntry * entry,
00056                                                nsCacheAccessMode accessGranted)
00057     : mCacheEntry(entry),
00058       mAccessGranted(accessGranted)
00059 {
00060     PR_INIT_CLIST(this);
00061     NS_ADDREF(nsCacheService::GlobalInstance());  // ensure it lives for the lifetime of the descriptor
00062 }
00063 
00064 
00065 nsCacheEntryDescriptor::~nsCacheEntryDescriptor()
00066 {
00067     // No need to close if the cache entry has already been severed.  This
00068     // helps avoid a shutdown assertion (bug 285519) that is caused when
00069     // consumers end up holding onto these objects past xpcom-shutdown.  It's
00070     // okay for them to do that because the cache service calls our Close
00071     // method during xpcom-shutdown, so we don't need to complain about it.
00072     if (mCacheEntry)
00073         Close();
00074 
00075     nsCacheService * service = nsCacheService::GlobalInstance();
00076     NS_RELEASE(service);
00077 }
00078 
00079 
00080 NS_IMETHODIMP
00081 nsCacheEntryDescriptor::GetClientID(char ** result)
00082 {
00083     NS_ENSURE_ARG_POINTER(result);
00084     nsAutoLock  lock(nsCacheService::ServiceLock());
00085     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00086 
00087     return ClientIDFromCacheKey(*(mCacheEntry->Key()), result);
00088 }
00089 
00090 
00091 NS_IMETHODIMP
00092 nsCacheEntryDescriptor::GetDeviceID(char ** result)
00093 {
00094     NS_ENSURE_ARG_POINTER(result);
00095     nsAutoLock  lock(nsCacheService::ServiceLock());
00096     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00097 
00098     *result = nsCRT::strdup(mCacheEntry->GetDeviceID());
00099     return *result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00100 }
00101 
00102 
00103 NS_IMETHODIMP
00104 nsCacheEntryDescriptor::GetKey(nsACString &result)
00105 {
00106     nsAutoLock  lock(nsCacheService::ServiceLock());
00107     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00108 
00109     return ClientKeyFromCacheKey(*(mCacheEntry->Key()), result);
00110 }
00111 
00112 
00113 NS_IMETHODIMP
00114 nsCacheEntryDescriptor::GetFetchCount(PRInt32 *result)
00115 {
00116     NS_ENSURE_ARG_POINTER(result);
00117     nsAutoLock  lock(nsCacheService::ServiceLock());
00118     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00119 
00120     *result = mCacheEntry->FetchCount();
00121     return NS_OK;
00122 }
00123 
00124 
00125 NS_IMETHODIMP
00126 nsCacheEntryDescriptor::GetLastFetched(PRUint32 *result)
00127 {
00128     NS_ENSURE_ARG_POINTER(result);
00129     nsAutoLock  lock(nsCacheService::ServiceLock());
00130     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00131 
00132     *result = mCacheEntry->LastFetched();
00133     return NS_OK;
00134 }
00135 
00136 
00137 NS_IMETHODIMP
00138 nsCacheEntryDescriptor::GetLastModified(PRUint32 *result)
00139 {
00140     NS_ENSURE_ARG_POINTER(result);
00141     nsAutoLock  lock(nsCacheService::ServiceLock());
00142     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00143 
00144     *result = mCacheEntry->LastModified();
00145     return NS_OK;
00146 }
00147 
00148 
00149 NS_IMETHODIMP
00150 nsCacheEntryDescriptor::GetExpirationTime(PRUint32 *result)
00151 {
00152     NS_ENSURE_ARG_POINTER(result);
00153     nsAutoLock  lock(nsCacheService::ServiceLock());
00154     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00155 
00156     *result = mCacheEntry->ExpirationTime();
00157     return NS_OK;
00158 }
00159 
00160 
00161 NS_IMETHODIMP
00162 nsCacheEntryDescriptor::SetExpirationTime(PRUint32 expirationTime)
00163 {
00164     nsAutoLock  lock(nsCacheService::ServiceLock());
00165     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00166 
00167     mCacheEntry->SetExpirationTime(expirationTime);
00168     mCacheEntry->MarkEntryDirty();
00169     return NS_OK;
00170 }
00171 
00172 
00173 NS_IMETHODIMP nsCacheEntryDescriptor::IsStreamBased(PRBool *result)
00174 {
00175     NS_ENSURE_ARG_POINTER(result);
00176     nsAutoLock  lock(nsCacheService::ServiceLock());
00177     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00178 
00179     *result = mCacheEntry->IsStreamData();
00180     return NS_OK;
00181 }
00182 
00183 
00184 NS_IMETHODIMP nsCacheEntryDescriptor::GetDataSize(PRUint32 *result)
00185 {
00186     NS_ENSURE_ARG_POINTER(result);
00187     nsAutoLock  lock(nsCacheService::ServiceLock());
00188     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00189 
00190     *result = mCacheEntry->DataSize();
00191     return NS_OK;
00192 }
00193 
00194 
00195 nsresult
00196 nsCacheEntryDescriptor::RequestDataSizeChange(PRInt32 deltaSize)
00197 {
00198     nsAutoLock  lock(nsCacheService::ServiceLock());
00199     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00200 
00201     nsresult  rv;
00202     rv = nsCacheService::OnDataSizeChange(mCacheEntry, deltaSize);
00203     if (NS_SUCCEEDED(rv)) {
00204         // XXX review for signed/unsigned math errors
00205         PRUint32  newDataSize = mCacheEntry->DataSize() + deltaSize;
00206         mCacheEntry->SetDataSize(newDataSize);
00207         mCacheEntry->TouchData();
00208     }
00209     return rv;
00210 }
00211 
00212 
00213 NS_IMETHODIMP
00214 nsCacheEntryDescriptor::SetDataSize(PRUint32 dataSize)
00215 {
00216     nsAutoLock  lock(nsCacheService::ServiceLock());
00217     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00218 
00219     // XXX review for signed/unsigned math errors
00220     PRInt32  deltaSize = dataSize - mCacheEntry->DataSize();
00221 
00222     nsresult  rv;
00223     rv = nsCacheService::OnDataSizeChange(mCacheEntry, deltaSize);
00224     // this had better be NS_OK, this call instance is advisory for memory cache objects
00225     if (NS_SUCCEEDED(rv)) {
00226         // XXX review for signed/unsigned math errors
00227         PRUint32  newDataSize = mCacheEntry->DataSize() + deltaSize;
00228         mCacheEntry->SetDataSize(newDataSize);
00229         mCacheEntry->TouchData();
00230     } else {
00231         NS_WARNING("failed SetDataSize() on memory cache object!");
00232     }
00233     
00234     return rv;
00235 }
00236 
00237 
00238 NS_IMETHODIMP
00239 nsCacheEntryDescriptor::OpenInputStream(PRUint32 offset, nsIInputStream ** result)
00240 {
00241     NS_ENSURE_ARG_POINTER(result);
00242 
00243     {
00244         nsAutoLock  lock(nsCacheService::ServiceLock());
00245         if (!mCacheEntry)                  return NS_ERROR_NOT_AVAILABLE;
00246         if (!mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
00247 
00248         // ensure valid permissions
00249         if (!(mAccessGranted & nsICache::ACCESS_READ))
00250             return NS_ERROR_CACHE_READ_ACCESS_DENIED;
00251     }
00252 
00253     nsInputStreamWrapper* cacheInput =
00254         new nsInputStreamWrapper(this, offset);
00255     if (!cacheInput) return NS_ERROR_OUT_OF_MEMORY;
00256 
00257     NS_ADDREF(*result = cacheInput);
00258     return NS_OK;
00259 }
00260 
00261 NS_IMETHODIMP
00262 nsCacheEntryDescriptor::OpenOutputStream(PRUint32 offset, nsIOutputStream ** result)
00263 {
00264     NS_ENSURE_ARG_POINTER(result);
00265 
00266     {
00267         nsAutoLock  lock(nsCacheService::ServiceLock());
00268         if (!mCacheEntry)                  return NS_ERROR_NOT_AVAILABLE;
00269         if (!mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
00270 
00271         // ensure valid permissions
00272         if (!(mAccessGranted & nsICache::ACCESS_WRITE))
00273             return NS_ERROR_CACHE_WRITE_ACCESS_DENIED;
00274     }
00275 
00276     nsOutputStreamWrapper* cacheOutput =
00277         new nsOutputStreamWrapper(this, offset);
00278     if (!cacheOutput) return NS_ERROR_OUT_OF_MEMORY;
00279 
00280     NS_ADDREF(*result = cacheOutput);
00281     return NS_OK;
00282 }
00283 
00284 
00285 NS_IMETHODIMP
00286 nsCacheEntryDescriptor::GetCacheElement(nsISupports ** result)
00287 {
00288     NS_ENSURE_ARG_POINTER(result);
00289     nsAutoLock  lock(nsCacheService::ServiceLock());
00290     if (!mCacheEntry)                 return NS_ERROR_NOT_AVAILABLE;
00291     if (mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_STREAM;
00292 
00293     NS_IF_ADDREF(*result = mCacheEntry->Data());
00294     return NS_OK;
00295 }
00296 
00297 
00298 NS_IMETHODIMP
00299 nsCacheEntryDescriptor::SetCacheElement(nsISupports * cacheElement)
00300 {
00301     nsAutoLock  lock(nsCacheService::ServiceLock());
00302     if (!mCacheEntry)                 return NS_ERROR_NOT_AVAILABLE;
00303     if (mCacheEntry->IsStreamData())  return NS_ERROR_CACHE_DATA_IS_STREAM;
00304 
00305     return nsCacheService::SetCacheElement(mCacheEntry, cacheElement);
00306 }
00307 
00308 
00309 NS_IMETHODIMP
00310 nsCacheEntryDescriptor::GetAccessGranted(nsCacheAccessMode *result)
00311 {
00312     NS_ENSURE_ARG_POINTER(result);
00313     *result = mAccessGranted;
00314     return NS_OK;
00315 }
00316 
00317 
00318 NS_IMETHODIMP
00319 nsCacheEntryDescriptor::GetStoragePolicy(nsCacheStoragePolicy *result)
00320 {
00321     NS_ENSURE_ARG_POINTER(result);
00322     nsAutoLock  lock(nsCacheService::ServiceLock());
00323     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00324     
00325     return mCacheEntry->StoragePolicy();
00326 }
00327 
00328 
00329 NS_IMETHODIMP
00330 nsCacheEntryDescriptor::SetStoragePolicy(nsCacheStoragePolicy policy)
00331 {
00332     nsAutoLock  lock(nsCacheService::ServiceLock());
00333     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00334     // XXX validate policy against session?
00335     
00336     PRBool      storageEnabled = PR_FALSE;
00337     storageEnabled = nsCacheService::IsStorageEnabledForPolicy_Locked(policy);
00338     if (!storageEnabled)    return NS_ERROR_FAILURE;
00339     
00340     mCacheEntry->SetStoragePolicy(policy);
00341     mCacheEntry->MarkEntryDirty();
00342     return NS_OK;
00343 }
00344 
00345 
00346 NS_IMETHODIMP
00347 nsCacheEntryDescriptor::GetFile(nsIFile ** result)
00348 {
00349     NS_ENSURE_ARG_POINTER(result);
00350     nsAutoLock  lock(nsCacheService::ServiceLock());
00351     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00352 
00353     return nsCacheService::GetFileForEntry(mCacheEntry, result);
00354 }
00355 
00356 
00357 NS_IMETHODIMP
00358 nsCacheEntryDescriptor::GetSecurityInfo(nsISupports ** result)
00359 {
00360     NS_ENSURE_ARG_POINTER(result);
00361     nsAutoLock  lock(nsCacheService::ServiceLock());
00362     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00363 
00364     return mCacheEntry->GetSecurityInfo(result);
00365 }
00366 
00367 
00368 NS_IMETHODIMP
00369 nsCacheEntryDescriptor::SetSecurityInfo(nsISupports * securityInfo)
00370 {
00371     nsAutoLock  lock(nsCacheService::ServiceLock());
00372     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00373 
00374     mCacheEntry->SetSecurityInfo(securityInfo);
00375     mCacheEntry->MarkEntryDirty();
00376     return NS_OK;
00377 }
00378 
00379 
00380 NS_IMETHODIMP
00381 nsCacheEntryDescriptor::Doom()
00382 {
00383     nsAutoLock  lock(nsCacheService::ServiceLock());
00384     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00385 
00386     return nsCacheService::DoomEntry(mCacheEntry);
00387 }
00388 
00389 
00390 NS_IMETHODIMP
00391 nsCacheEntryDescriptor::DoomAndFailPendingRequests(nsresult status)
00392 {
00393     nsAutoLock  lock(nsCacheService::ServiceLock());
00394     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00395 
00396     return NS_ERROR_NOT_IMPLEMENTED;
00397 }
00398 
00399 
00400 NS_IMETHODIMP
00401 nsCacheEntryDescriptor::MarkValid()
00402 {
00403     nsAutoLock  lock(nsCacheService::ServiceLock());
00404     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00405 
00406     nsresult  rv = nsCacheService::ValidateEntry(mCacheEntry);
00407     return rv;
00408 }
00409 
00410 
00411 NS_IMETHODIMP
00412 nsCacheEntryDescriptor::Close()
00413 {
00414     nsAutoLock  lock(nsCacheService::ServiceLock());
00415     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00416 
00417     // XXX perhaps closing descriptors should clear/sever transports
00418 
00419     // tell nsCacheService we're going away
00420     nsCacheService::CloseDescriptor(this);
00421     NS_ASSERTION(mCacheEntry == nsnull, "mCacheEntry not null");
00422 
00423     return NS_OK;
00424 }
00425 
00426 
00427 NS_IMETHODIMP
00428 nsCacheEntryDescriptor::GetMetaDataElement(const char *key, char ** result)
00429 {
00430     *result = nsnull;
00431 
00432     nsAutoLock  lock(nsCacheService::ServiceLock());
00433     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00434 
00435     if (!key | !result) return NS_ERROR_NULL_POINTER;
00436     const char *value;
00437 
00438     value = mCacheEntry->GetMetaDataElement(key);
00439     if (!value) return NS_ERROR_NOT_AVAILABLE;
00440 
00441     *result = PL_strdup(value);
00442     if (!*result) return NS_ERROR_OUT_OF_MEMORY;
00443 
00444     return NS_OK;
00445 }
00446 
00447 
00448 NS_IMETHODIMP
00449 nsCacheEntryDescriptor::SetMetaDataElement(const char *key, const char *value)
00450 {
00451     nsAutoLock  lock(nsCacheService::ServiceLock());
00452     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00453 
00454     if (!key) return NS_ERROR_NULL_POINTER;
00455 
00456     // XXX allow null value, for clearing key?
00457 
00458     nsresult rv = mCacheEntry->SetMetaDataElement(key, value);
00459     if (NS_SUCCEEDED(rv))
00460         mCacheEntry->TouchMetaData();
00461     return rv;
00462 }
00463 
00464 
00465 NS_IMETHODIMP
00466 nsCacheEntryDescriptor::VisitMetaData(nsICacheMetaDataVisitor * visitor)
00467 {
00468     nsAutoLock  lock(nsCacheService::ServiceLock());      // XXX check callers, we're calling out of module
00469     NS_ENSURE_ARG_POINTER(visitor);
00470     if (!mCacheEntry)  return NS_ERROR_NOT_AVAILABLE;
00471 
00472     return mCacheEntry->VisitMetaDataElements(visitor);
00473 }
00474 
00475 
00476 /******************************************************************************
00477  * nsCacheInputStream - a wrapper for nsIInputstream keeps the cache entry
00478  *                      open while referenced.
00479  ******************************************************************************/
00480 
00481 NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheEntryDescriptor::nsInputStreamWrapper,
00482                               nsIInputStream)
00483 
00484 nsresult nsCacheEntryDescriptor::
00485 nsInputStreamWrapper::LazyInit()
00486 {
00487     nsAutoLock lock(nsCacheService::ServiceLock());
00488 
00489     nsCacheAccessMode mode;
00490     nsresult rv = mDescriptor->GetAccessGranted(&mode);
00491     if (NS_FAILED(rv)) return rv;
00492 
00493     NS_ENSURE_TRUE(mode & nsICache::ACCESS_READ, NS_ERROR_UNEXPECTED);
00494 
00495     nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
00496     if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
00497 
00498     nsCOMPtr<nsIInputStream> input;
00499     rv = nsCacheService::OpenInputStreamForEntry(cacheEntry, mode,
00500                                                  mStartOffset,
00501                                                  getter_AddRefs(mInput));
00502     if (NS_FAILED(rv)) return rv;
00503 
00504     mInitialized = PR_TRUE;
00505     return NS_OK;
00506 }
00507 
00508 nsresult nsCacheEntryDescriptor::
00509 nsInputStreamWrapper::Close()
00510 {
00511     nsresult rv = EnsureInit();
00512     if (NS_FAILED(rv)) return rv;
00513 
00514     return mInput->Close();
00515 }
00516 
00517 nsresult nsCacheEntryDescriptor::
00518 nsInputStreamWrapper::Available(PRUint32 *avail)
00519 {
00520     nsresult rv = EnsureInit();
00521     if (NS_FAILED(rv)) return rv;
00522 
00523     return mInput->Available(avail);
00524 }
00525 
00526 nsresult nsCacheEntryDescriptor::
00527 nsInputStreamWrapper::Read(char *buf, PRUint32 count, PRUint32 *countRead)
00528 {
00529     nsresult rv = EnsureInit();
00530     if (NS_FAILED(rv)) return rv;
00531 
00532     return mInput->Read(buf, count, countRead);
00533 }
00534 
00535 nsresult nsCacheEntryDescriptor::
00536 nsInputStreamWrapper::ReadSegments(nsWriteSegmentFun writer, void *closure,
00537                                    PRUint32 count, PRUint32 *countRead)
00538 {
00539     // cache stream not buffered
00540     return NS_ERROR_NOT_IMPLEMENTED;
00541 }
00542 
00543 nsresult nsCacheEntryDescriptor::
00544 nsInputStreamWrapper::IsNonBlocking(PRBool *result)
00545 {
00546     // cache streams will never return NS_BASE_STREAM_WOULD_BLOCK
00547     *result = PR_FALSE;
00548     return NS_OK;
00549 }
00550 
00551 
00552 /******************************************************************************
00553  * nsCacheOutputStream - a wrapper for nsIOutputstream to track the amount of
00554  *                       data written to a cache entry.
00555  *                     - also keeps the cache entry open while referenced.
00556  ******************************************************************************/
00557 
00558 NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheEntryDescriptor::nsOutputStreamWrapper,
00559                               nsIOutputStream)
00560 
00561 nsresult nsCacheEntryDescriptor::
00562 nsOutputStreamWrapper::LazyInit()
00563 {
00564     nsAutoLock lock(nsCacheService::ServiceLock());
00565 
00566     nsCacheAccessMode mode;
00567     nsresult rv = mDescriptor->GetAccessGranted(&mode);
00568     if (NS_FAILED(rv)) return rv;
00569 
00570     NS_ENSURE_TRUE(mode & nsICache::ACCESS_WRITE, NS_ERROR_UNEXPECTED);
00571 
00572     nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
00573     if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
00574 
00575     rv = nsCacheService::OpenOutputStreamForEntry(cacheEntry, mode, mStartOffset,
00576                                                   getter_AddRefs(mOutput));
00577     if (NS_FAILED(rv)) return rv;
00578 
00579     nsCacheDevice* device = cacheEntry->CacheDevice();
00580     if (!device) return NS_ERROR_NOT_AVAILABLE;
00581 
00582     // the entry has been truncated to mStartOffset bytes, inform the device.
00583     PRInt32 size = cacheEntry->DataSize();
00584     rv = device->OnDataSizeChange(cacheEntry, mStartOffset - size);
00585     if (NS_FAILED(rv)) return rv;
00586 
00587     cacheEntry->SetDataSize(mStartOffset);
00588 
00589     mInitialized = PR_TRUE;
00590     return NS_OK;
00591 }
00592 
00593 nsresult nsCacheEntryDescriptor::
00594 nsOutputStreamWrapper::OnWrite(PRUint32 count)
00595 {
00596     if (count > PR_INT32_MAX)  return NS_ERROR_UNEXPECTED;
00597     return mDescriptor->RequestDataSizeChange((PRInt32)count);
00598 }
00599 
00600 NS_IMETHODIMP nsCacheEntryDescriptor::
00601 nsOutputStreamWrapper::Close()
00602 {
00603     nsresult rv = EnsureInit();
00604     if (NS_FAILED(rv)) return rv;
00605 
00606     return mOutput->Close();
00607 }
00608 
00609 NS_IMETHODIMP nsCacheEntryDescriptor::
00610 nsOutputStreamWrapper::Flush()
00611 {
00612     nsresult rv = EnsureInit();
00613     if (NS_FAILED(rv)) return rv;
00614 
00615     return mOutput->Flush();
00616 }
00617 
00618 NS_IMETHODIMP nsCacheEntryDescriptor::
00619 nsOutputStreamWrapper::Write(const char * buf,
00620                              PRUint32     count,
00621                              PRUint32 *   result)
00622 {
00623     nsresult rv = EnsureInit();
00624     if (NS_FAILED(rv)) return rv;
00625 
00626     rv = OnWrite(count);
00627     if (NS_FAILED(rv)) return rv;
00628 
00629     return mOutput->Write(buf, count, result);
00630 }
00631 
00632 NS_IMETHODIMP nsCacheEntryDescriptor::
00633 nsOutputStreamWrapper::WriteFrom(nsIInputStream * inStr,
00634                                  PRUint32         count,
00635                                  PRUint32 *       result)
00636 {
00637     NS_NOTREACHED("cache stream not buffered");
00638     return NS_ERROR_NOT_IMPLEMENTED;
00639 }
00640 
00641 NS_IMETHODIMP nsCacheEntryDescriptor::
00642 nsOutputStreamWrapper::WriteSegments(nsReadSegmentFun  reader,
00643                                      void *            closure,
00644                                      PRUint32          count,
00645                                      PRUint32 *        result)
00646 {
00647     NS_NOTREACHED("cache stream not buffered");
00648     return NS_ERROR_NOT_IMPLEMENTED;
00649 }
00650 
00651 NS_IMETHODIMP nsCacheEntryDescriptor::
00652 nsOutputStreamWrapper::IsNonBlocking(PRBool *result)
00653 {
00654     // cache streams will never return NS_BASE_STREAM_WOULD_BLOCK
00655     *result = PR_FALSE;
00656     return NS_OK;
00657 }