|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Asynchronous file copy, implemented with several small sync block copies.* |
|
15 */ |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <mpxlog.h> |
|
22 #include <bautils.h> |
|
23 #include "vcxmyvideosasyncfilecopy.h" |
|
24 |
|
25 /** |
|
26 * One block shouldn't take more than 1 second to copy to keep cancel |
|
27 * response fast enough. On the otherhand, the deleting the already |
|
28 * copied data may take several seconds. |
|
29 * |
|
30 * Copying speed tests (from massmemory to memorycard): |
|
31 * |
|
32 * Block size speed response time |
|
33 * 6MB -> 3.20 MB/s ~2sec (unacceptable response time, full speed) |
|
34 * 3MB -> 3.17 MB/s ~1sec (poor response time, almost full speed) |
|
35 * 1MB -> 3.16 MB/s ~0.3sec (good response time, almost full speed) |
|
36 * 0.5MB -> 2.60 MB/s ~0.19sec (good response time, some speed loss) |
|
37 * |
|
38 * -> 1MB is the best. |
|
39 * |
|
40 * * Copying speed tests (from memorycard to massmemory): |
|
41 * |
|
42 * Block size speed response time |
|
43 * 3MB -> 5.470 MB/s 0.548sec |
|
44 * 1MB -> 4.393 MB/s 0.228sec |
|
45 * |
|
46 * 1M gives slightly reduced speed, great response time. 3MB would be better than |
|
47 * 1M but can't use it since it gives 1sec response time in memorycard writing. |
|
48 */ |
|
49 const TInt KBigBufSize = 1024 * 1024; // 1MB |
|
50 const TInt KMediumBufSize = 512 * 1024; // 0.5MB |
|
51 const TInt KSmallBufSize = 100 * 1024; // 0.1MB |
|
52 |
|
53 // ============================ MEMBER FUNCTIONS ============================== |
|
54 |
|
55 // ---------------------------------------------------------------------------- |
|
56 // Two-phased constructor. |
|
57 // ---------------------------------------------------------------------------- |
|
58 // |
|
59 CVcxMyVideosAsyncFileCopy* CVcxMyVideosAsyncFileCopy::NewL( RFs& aFs ) |
|
60 { |
|
61 CVcxMyVideosAsyncFileCopy* self = new (ELeave) CVcxMyVideosAsyncFileCopy( aFs ); |
|
62 CleanupStack::PushL(self); |
|
63 self->ConstructL(); |
|
64 CleanupStack::Pop(self); |
|
65 return self; |
|
66 } |
|
67 |
|
68 // ---------------------------------------------------------------------------- |
|
69 // Destructor. |
|
70 // ---------------------------------------------------------------------------- |
|
71 // |
|
72 CVcxMyVideosAsyncFileCopy::~CVcxMyVideosAsyncFileCopy() |
|
73 { |
|
74 iSourceFile.Close(); |
|
75 iTargetFile.Close(); |
|
76 delete iFileBlockBuffer; |
|
77 } |
|
78 |
|
79 // ---------------------------------------------------------------------------- |
|
80 // Constructor. |
|
81 // ---------------------------------------------------------------------------- |
|
82 // |
|
83 CVcxMyVideosAsyncFileCopy::CVcxMyVideosAsyncFileCopy( RFs& aFs ) |
|
84 : iFs( aFs ) |
|
85 { |
|
86 } |
|
87 |
|
88 // ---------------------------------------------------------------------------- |
|
89 // Symbian 2nd phase constructor can leave. |
|
90 // ---------------------------------------------------------------------------- |
|
91 // |
|
92 void CVcxMyVideosAsyncFileCopy::ConstructL () |
|
93 { |
|
94 } |
|
95 |
|
96 // ---------------------------------------------------------------------------- |
|
97 // CVcxMyVideosAsyncFileCopy::CopyL |
|
98 // ---------------------------------------------------------------------------- |
|
99 // |
|
100 TBool CVcxMyVideosAsyncFileCopy::CopyL( const TDesC& aSourceFileName, |
|
101 const TDesC& aTargetFileName ) |
|
102 { |
|
103 MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::CopyL() start"); |
|
104 |
|
105 if ( iIsCopying ) |
|
106 { |
|
107 User::Leave( KErrNotReady ); |
|
108 } |
|
109 |
|
110 TInt error = iSourceFile.Open( iFs, aSourceFileName, EFileRead | EFileShareReadersOnly ); |
|
111 |
|
112 User::LeaveIfError( error ); |
|
113 |
|
114 error = iTargetFile.Replace( iFs, aTargetFileName, EFileWrite | EFileWriteDirectIO |
|
115 | EFileShareExclusive ); |
|
116 |
|
117 if ( error == KErrPathNotFound ) |
|
118 { |
|
119 error = iFs.MkDirAll( aTargetFileName ); |
|
120 if ( error == KErrNone ) |
|
121 { |
|
122 error = iTargetFile.Create( iFs, aTargetFileName, EFileWrite |
|
123 | EFileWriteDirectIO | EFileShareExclusive ); |
|
124 } |
|
125 } |
|
126 |
|
127 User::LeaveIfError( error ); |
|
128 User::LeaveIfError( iSourceFile.Size( iDataRemaining ) ); |
|
129 User::LeaveIfError( iTargetFile.SetSize( iDataRemaining ) ); |
|
130 |
|
131 TInt suggestBlockSize; |
|
132 if ( iDataRemaining > KBigBufSize ) |
|
133 { |
|
134 suggestBlockSize = KBigBufSize; |
|
135 } |
|
136 else |
|
137 { |
|
138 suggestBlockSize = iDataRemaining; |
|
139 } |
|
140 AllocateFileBlockBufferL( suggestBlockSize ); |
|
141 |
|
142 iReadPos = 0; |
|
143 iIsCopying = ETrue; |
|
144 |
|
145 #ifdef _DEBUG |
|
146 iStartTime.UniversalTime(); |
|
147 #endif |
|
148 |
|
149 DoNextBlockCopy(); |
|
150 |
|
151 MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::CopyL() exit"); |
|
152 return !iIsCopying; |
|
153 } |
|
154 |
|
155 // ---------------------------------------------------------------------------- |
|
156 // CVcxMyVideosAsyncFileCopy::CopyIsOngoing |
|
157 // ---------------------------------------------------------------------------- |
|
158 // |
|
159 TBool CVcxMyVideosAsyncFileCopy::CopyIsOngoing() |
|
160 { |
|
161 return iIsCopying; |
|
162 } |
|
163 |
|
164 // ---------------------------------------------------------------------------- |
|
165 // CVcxMyVideosAsyncFileCopy::DoNextBlockCopy |
|
166 // ---------------------------------------------------------------------------- |
|
167 // |
|
168 TInt CVcxMyVideosAsyncFileCopy::DoNextBlockCopy() |
|
169 { |
|
170 TInt err = KErrNone; |
|
171 TPtr8 fileBufPtr = iFileBlockBuffer->Des(); |
|
172 |
|
173 TInt bytesToCopy = Min( iDataRemaining, fileBufPtr.MaxSize() ); |
|
174 |
|
175 err = iSourceFile.Read( iReadPos, fileBufPtr, bytesToCopy ); |
|
176 if ( err == KErrNone && fileBufPtr.Length() != bytesToCopy ) |
|
177 { |
|
178 err = KErrCorrupt; |
|
179 } |
|
180 if ( err == KErrNone ) |
|
181 { |
|
182 err = iTargetFile.Write( iReadPos, fileBufPtr, bytesToCopy ); |
|
183 } |
|
184 if ( err != KErrNone ) |
|
185 { |
|
186 EndCopy( ETrue /* remove target file */); |
|
187 return err; |
|
188 } |
|
189 |
|
190 iReadPos += bytesToCopy; |
|
191 iDataRemaining -= bytesToCopy; |
|
192 |
|
193 if ( iDataRemaining == 0 ) |
|
194 { |
|
195 EndCopy( EFalse /* keep target file */); |
|
196 } |
|
197 |
|
198 return KErrNone; |
|
199 } |
|
200 |
|
201 // ---------------------------------------------------------------------------- |
|
202 // CVcxMyVideosAsyncFileCopy::Cancel |
|
203 // ---------------------------------------------------------------------------- |
|
204 // |
|
205 void CVcxMyVideosAsyncFileCopy::Cancel() |
|
206 { |
|
207 MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::Cancel() start"); |
|
208 |
|
209 if ( iIsCopying ) |
|
210 { |
|
211 EndCopy( ETrue /* remove target file */ ); |
|
212 } |
|
213 MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::Cancel() exit"); |
|
214 } |
|
215 |
|
216 // ---------------------------------------------------------------------------- |
|
217 // CVcxMyVideosAsyncFileCopy::AllocateFileBlockBufferL |
|
218 // ---------------------------------------------------------------------------- |
|
219 // |
|
220 void CVcxMyVideosAsyncFileCopy::AllocateFileBlockBufferL( TInt aFileSize ) |
|
221 { |
|
222 delete iFileBlockBuffer; |
|
223 iFileBlockBuffer = NULL; |
|
224 |
|
225 TInt big = Min( aFileSize, KBigBufSize ); |
|
226 iFileBlockBuffer = HBufC8::New( big ); |
|
227 if ( !iFileBlockBuffer ) |
|
228 { |
|
229 iFileBlockBuffer = HBufC8::New( KMediumBufSize ); |
|
230 } |
|
231 if ( !iFileBlockBuffer ) |
|
232 { |
|
233 iFileBlockBuffer = HBufC8::NewL( KSmallBufSize ); |
|
234 } |
|
235 } |
|
236 |
|
237 void CVcxMyVideosAsyncFileCopy::EndCopy( TBool aRemoveTargetFile ) |
|
238 { |
|
239 MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::EndCopy() start"); |
|
240 |
|
241 TTime modified; |
|
242 iSourceFile.Modified( modified ); |
|
243 iTargetFile.SetModified( modified ); |
|
244 |
|
245 #ifdef _DEBUG |
|
246 |
|
247 TDateTime dT = modified.DateTime(); |
|
248 TBuf<200> buf; |
|
249 buf.Format(_L("CVcxMyVideosAsyncFileCopy:: setting file modified date: %2d.%2d.%4d %2d:%2d:%2d"), |
|
250 dT.Day()+1, dT.Month()+1, dT.Year(), dT.Hour(), dT.Minute(), dT.Second() ); |
|
251 MPX_DEBUG2("%S", &buf ); |
|
252 |
|
253 const TInt megaBytes = 0x100000; |
|
254 const TInt kiloBytes = 1024; |
|
255 TInt dataCopiedInMegaBytes = iReadPos / megaBytes; |
|
256 TTime now; |
|
257 now.UniversalTime(); |
|
258 TTimeIntervalSeconds interval; |
|
259 now.SecondsFrom( iStartTime, interval ); |
|
260 TInt copyingSpeed = 0; |
|
261 if ( interval.Int() > 0 ) |
|
262 { |
|
263 copyingSpeed = (iReadPos / kiloBytes) / interval.Int(); |
|
264 } |
|
265 MPX_DEBUG3("CVcxMyVideosAsyncFileCopy:: Data copied: %d (MB), %d kB/s", dataCopiedInMegaBytes, copyingSpeed); |
|
266 #endif |
|
267 |
|
268 delete iFileBlockBuffer; |
|
269 iFileBlockBuffer = NULL; |
|
270 iReadPos = 0; |
|
271 iDataRemaining = 0; |
|
272 iSourceFile.Close(); |
|
273 iIsCopying = EFalse; |
|
274 |
|
275 if ( aRemoveTargetFile ) |
|
276 { |
|
277 TFileName fileName; |
|
278 TInt err = iTargetFile.FullName( fileName ); |
|
279 |
|
280 iTargetFile.Close(); |
|
281 |
|
282 if ( err == KErrNone ) |
|
283 { |
|
284 MPX_DEBUG2("CVcxMyVideosAsyncFileCopy:: removing file: %S", &fileName); |
|
285 iFs.Delete( fileName ); |
|
286 } |
|
287 } |
|
288 else |
|
289 { |
|
290 iTargetFile.Close(); |
|
291 } |
|
292 |
|
293 MPX_DEBUG1("CVcxMyVideosAsyncFileCopy::EndCopy() exit"); |
|
294 } |