1 /* This FileX test concentrates on the Fault-Tolerant write large data interrupt test. */
2 /*
3 For FAT 12, 16, 32, one cluster size is 1024 bytes;
4 Check write large data fat interrupt operation:
5 Step1: Format and open the media;
6 Step2: Enable fault tolerant feature;
7 Step3: Create new file called "TEST.TXT";
8 Step4: Get the media available bytes;
9 Step5: Write large bytes out of the file to fill the media
10 Step7: Terminate the new thread to simulate poweroff when update the data between undo log generated and redo log not generated.
11 Step8: Open the media;
12 Step9: Enable fault tolerant feature to recover the data(undo operation);
13 Step10: Check the test files.
14 */
15 #ifndef FX_STANDALONE_ENABLE
16 #include "tx_api.h"
17 #else
18 #define _GNU_SOURCE
19 #define _DEFAULT_SOURCE
20 #include <pthread.h>
21 #include <unistd.h>
22 #endif
23 #include "fx_api.h"
24 #include "fx_system.h"
25 #include "fx_fault_tolerant.h"
26 #include <stdio.h>
27 #include <time.h>
28 #include "fx_ram_driver_test.h"
29 extern void test_control_return(UINT status);
30 void filex_fault_tolerant_write_large_data_interrupt_test_application_define(void *first_unused_memory);
31
32 #if defined (FX_ENABLE_FAULT_TOLERANT) && defined (FX_FAULT_TOLERANT)
33
34 #define DEMO_STACK_SIZE 4096
35 #define CACHE_SIZE 2048
36 #define FAULT_TOLERANT_SIZE FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
37
38
39 /* Define the ThreadX and FileX object control blocks... */
40
41 #ifndef FX_STANDALONE_ENABLE
42 static TX_THREAD ftest_0;
43 static TX_THREAD ftest_1;
44 #else
45 static pthread_t ptid1;
46 #endif
47 static FX_MEDIA ram_disk;
48 static FX_FILE my_file;
49 static UCHAR *pointer;
50
51 /* Define the counters used in the test application... */
52
53 #ifndef FX_STANDALONE_ENABLE
54 static UCHAR *cache_buffer;
55 static UCHAR *fault_tolerant_buffer;
56 static UCHAR *thread_buffer;
57 #else
58 static UCHAR cache_buffer[CACHE_SIZE];
59 static UCHAR fault_tolerant_buffer[FAULT_TOLERANT_SIZE];
60 #endif
61 static UINT error_couter = 0;
62 static ULONG write_data_size;
63 static ULONG available_bytes;
64 static UINT data_write_interrupt = FX_FALSE;
65 static ULONG i, j;
66
67 #define TEST_COUNT 3
68
69 /* Define thread prototypes. */
70
71 static void ftest_0_entry(ULONG thread_input);
72 #ifndef FX_STANDALONE_ENABLE
73 static void ftest_1_entry(ULONG thread_input);
74 #else
75 static void * ftest_1_entry(void * thread_input);
76 #endif
77
78 extern void _fx_ram_driver(FX_MEDIA *media_ptr);
79 extern void test_control_return(UINT status);
80 extern UINT _filex_fault_tolerant_log_check(FX_MEDIA *media_ptr);
81 extern UINT (*driver_write_callback)(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr);
82 static UINT my_driver_write(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr);
83
84
85 /* Define what the initial system looks like. */
86
87 #ifdef CTEST
test_application_define(void * first_unused_memory)88 void test_application_define(void *first_unused_memory)
89 #else
90 void filex_fault_tolerant_write_large_data_interrupt_test_application_define(void *first_unused_memory)
91 #endif
92 {
93
94 #ifndef FX_STANDALONE_ENABLE
95 /* Setup the working pointer. */
96 pointer = (UCHAR *) first_unused_memory;
97
98 /* Create the main thread. */
99
100 tx_thread_create(&ftest_0, "thread 0", ftest_0_entry, 0,
101 pointer, DEMO_STACK_SIZE,
102 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
103
104 pointer = pointer + DEMO_STACK_SIZE;
105
106 /* Setup memory for the RAM disk and the sector cache. */
107 cache_buffer = pointer;
108 pointer += CACHE_SIZE;
109 fault_tolerant_buffer = pointer;
110 pointer += FAULT_TOLERANT_SIZE;
111 thread_buffer = pointer;
112 pointer += DEMO_STACK_SIZE;
113 #endif
114
115 /* Initialize the FileX system. */
116 fx_system_initialize();
117 #ifdef FX_STANDALONE_ENABLE
118 ftest_0_entry(0);
119 #endif
120 }
121
122
123 /* Define the test threads. */
124
ftest_0_entry(ULONG thread_input)125 static void ftest_0_entry(ULONG thread_input)
126 {
127
128 UINT status;
129 ULONG actual;
130 ULONG data_value;
131
132 FX_PARAMETER_NOT_USED(thread_input);
133
134 /* Print out some test information banners. */
135 printf("FileX Test: Fault Tolerant Write Large Data Interrupt test.........");
136
137 /* Generate a random number for write data. */
138 srand((ULONG)time(NULL));
139 data_value = (ULONG)(rand() & 0xFF) | (ULONG)((rand() & 0xFF) << 8) | (ULONG)((rand() & 0xFF) << 16) | (ULONG)((rand() & 0xFF) << 24);
140
141 /* Genearte the write data. */
142 for (j = 0; j < large_data_buffer_size / sizeof(ULONG); j ++)
143 {
144 ((ULONG*)large_data_buffer)[j] = data_value++;
145 }
146
147 /* Roll back the value for later verification use. */
148 data_value -= (large_data_buffer_size / sizeof(ULONG));
149
150 /* Loop to test FAT 12, 16, 32. */
151 for (i = 0; i < TEST_COUNT; i ++)
152 {
153 if (i == 0)
154 {
155 /* Format the media with FAT12. This needs to be done before opening it! */
156 status = fx_media_format(&ram_disk,
157 _fx_ram_driver, // Driver entry
158 ram_disk_memory_large, // RAM disk memory pointer
159 cache_buffer, // Media buffer pointer
160 CACHE_SIZE, // Media buffer size
161 "MY_RAM_DISK", // Volume Name
162 1, // Number of FATs
163 32, // Directory Entries
164 0, // Hidden sectors
165 4000 * 8, // Total sectors
166 256, // Sector size
167 8, // Sectors per cluster
168 1, // Heads
169 1); // Sectors per track
170 }
171 else if (i == 1)
172 {
173 /* Format the media with FAT16. This needs to be done before opening it! */
174 status = fx_media_format(&ram_disk,
175 _fx_ram_driver, // Driver entry
176 ram_disk_memory_large, // RAM disk memory pointer
177 cache_buffer, // Media buffer pointer
178 CACHE_SIZE, // Media buffer size
179 "MY_RAM_DISK", // Volume Name
180 1, // Number of FATs
181 32, // Directory Entries
182 0, // Hidden sectors
183 60000 * 8, // Total sectors
184 256, // Sector size
185 8, // Sectors per cluster
186 1, // Heads
187 1); // Sectors per track
188 }
189 else if (i == 2)
190 {
191 /* Format the media with FAT32. This needs to be done before opening it! */
192 status = fx_media_format(&ram_disk,
193 _fx_ram_driver, // Driver entry
194 ram_disk_memory_large, // RAM disk memory pointer
195 cache_buffer, // Media buffer pointer
196 CACHE_SIZE, // Media buffer size
197 "MY_RAM_DISK", // Volume Name
198 1, // Number of FATs
199 32, // Directory Entries
200 0, // Hidden sectors
201 400000 * 8, // Total sectors
202 256, // Sector size
203 8, // Sectors per cluster
204 1, // Heads
205 1); // Sectors per track
206 }
207
208 /* Determine if the format had an error. */
209 if (status)
210 {
211
212 printf("ERROR!\n");
213 test_control_return(1);
214 }
215
216 /* Open the ram_disk. */
217 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
218
219 /* Check the status. */
220 if (status != FX_SUCCESS)
221 {
222
223 /* Error, return error code. */
224 printf("ERROR!\n");
225 test_control_return(2);
226 }
227
228 /* Enable the Fault-tolerant feature. */
229 status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
230
231 /* Check status. */
232 if (status)
233 {
234
235 printf("ERROR!\n");
236 test_control_return(3);
237 }
238
239 /* Create a file called TEST.TXT in the root directory. */
240 status = fx_file_create(&ram_disk, "TEST.TXT");
241
242 /* Check the create status. */
243 if (status != FX_SUCCESS)
244 {
245
246 printf("ERROR!\n");
247 test_control_return(4);
248 }
249
250 /* Open the test file. */
251 status = fx_file_open(&ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
252
253 /* Check the file open status. */
254 if (status != FX_SUCCESS)
255 {
256
257 printf("ERROR!\n");
258 test_control_return(5);
259 }
260
261 /* Pickup the available bytes in the media. */
262 status = fx_media_space_available(&ram_disk, &available_bytes);
263
264 /* Check for available bytes error. */
265 if ((status != FX_SUCCESS) || (available_bytes < sizeof(ULONG)))
266 {
267
268 printf("ERROR!\n");
269 test_control_return(6);
270 }
271
272 write_data_size = available_bytes;
273
274 /* Create the main thread. */
275 #ifndef FX_STANDALONE_ENABLE
276 tx_thread_create(&ftest_1, "thread 1", ftest_1_entry, 0,
277 thread_buffer, DEMO_STACK_SIZE,
278 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
279 #endif
280
281 /* data_write_interrupt */
282 data_write_interrupt = FX_FALSE;
283
284 /* Let the other thread run. */
285 #ifndef FX_STANDALONE_ENABLE
286 tx_thread_relinquish();
287 #else
288 pthread_create(&ptid1, NULL, &ftest_1_entry, NULL);
289 usleep(10);
290 pthread_join(ptid1,NULL);
291 #endif
292
293 /* Open the ram_disk. */
294 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
295
296 /* Check the status. */
297 if (status != FX_SUCCESS)
298 {
299
300 /* Error, return error code. */
301 printf("ERROR!\n");
302 test_control_return(8);
303 }
304
305 /* Enable the Fault-tolerant feature. */
306 status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
307
308 /* Check status. */
309 if (status)
310 {
311
312 printf("ERROR!\n");
313 test_control_return(9);
314 }
315
316 /* Pickup the available bytes in the media again. */
317 status = fx_media_space_available(&ram_disk, &j);
318
319 /* Check for available bytes error. */
320 if ((status != FX_SUCCESS) || (j != available_bytes))
321 {
322
323 printf("ERROR!\n");
324 test_control_return(10);
325 }
326
327 /* Open the test file. */
328 status = fx_file_open(&ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
329
330 /* Check the file open status. */
331 if (status != FX_SUCCESS)
332 {
333
334 printf("ERROR!\n");
335 test_control_return(11);
336 }
337
338 /* Seek to the beginning of the test file. */
339 status = fx_file_seek(&my_file, 0);
340
341 /* Check the file seek status. */
342 if (status != FX_SUCCESS)
343 {
344
345 printf("ERROR!\n");
346 test_control_return(12);
347 }
348
349 /* Now read in all the bytes again to make sure the file contents are really there. */
350 status = fx_file_read(&my_file, (void *) large_data_buffer, large_data_buffer_size, &actual);
351
352 /* Check the file read status. */
353 if ((status != FX_END_OF_FILE) || (actual != 0))
354 {
355
356 printf("ERROR!\n");
357 test_control_return(13);
358 }
359
360 /* Close the test file. */
361 status = fx_file_close(&my_file);
362
363 /* Check the file close status. */
364 if (status != FX_SUCCESS)
365 {
366
367 printf("ERROR!\n");
368 test_control_return(14);
369 }
370
371 /* Close the media. */
372 status = fx_media_close(&ram_disk);
373
374 /* Determine if the test was successful. */
375 if ((status != FX_SUCCESS) || (data_write_interrupt != FX_TRUE) || (error_couter))
376 {
377
378 printf("ERROR!\n");
379 test_control_return(15);
380 }
381
382 /* Delete the thread. */
383 #ifndef FX_STANDALONE_ENABLE
384 tx_thread_delete(&ftest_1);
385 #else
386 pthread_cancel(ptid1);
387 #endif
388 }
389
390 /* Output successful. */
391 printf("SUCCESS!\n");
392 test_control_return(0);
393 }
394
395 /* Define the test threads. */
396
397 #ifndef FX_STANDALONE_ENABLE
ftest_1_entry(ULONG thread_input)398 static void ftest_1_entry(ULONG thread_input)
399 #else
400 void * ftest_1_entry(void * thread_input)
401 #endif
402 {
403
404 #ifdef FX_STANDALONE_ENABLE
405 UINT oldtype;
406 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
407 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
408 #endif
409 UINT status;
410 FX_PARAMETER_NOT_USED(thread_input);
411
412 /* Set the callback function to simulate poweoff operation when write FAT entry. */
413 driver_write_callback = my_driver_write;
414
415 /* Write the data to fill the media one time. */
416 status = fx_file_write(&my_file, (void *) large_data_buffer, write_data_size);
417
418 /* Check the file write status. */
419 if (status != FX_SUCCESS)
420 {
421 #ifndef FX_STANDALONE_ENABLE
422 return;
423 #else
424 return NULL;
425 #endif
426 }
427 }
428
my_driver_write(FX_MEDIA * media_ptr,UINT sector_type,UCHAR * block_ptr,UINT * operation_ptr)429 static UINT my_driver_write(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr)
430 {
431
432 FX_PARAMETER_NOT_USED(block_ptr);
433
434 /* Interrupt the data write operation after record the undo log. */
435 if ((sector_type == FX_DATA_SECTOR) && (_filex_fault_tolerant_log_check(media_ptr) & FX_FAULT_TOLERANT_LOG_UNDO_DONE) &&
436 (!(_filex_fault_tolerant_log_check(media_ptr) & FX_FAULT_TOLERANT_LOG_REDO_DONE)))
437 {
438
439 /* Set the write interrupt operation. */
440 *operation_ptr = FX_OP_WRITE_INTERRUPT;
441
442 /* Update the flag. */
443 data_write_interrupt = FX_TRUE;
444
445 /* Clean the callback function. */
446 driver_write_callback = FX_NULL;
447
448 /* Delete the media protection structure if FX_SINGLE_THREAD is not
449 defined. */
450 #ifndef FX_SINGLE_THREAD
451 #ifndef FX_DONT_CREATE_MUTEX
452
453 /* Note that the protection is never released. The mutex delete
454 service will handle all threads waiting access to this media
455 control block. */
456 tx_mutex_delete(&(media_ptr -> fx_media_protect));
457 #endif
458 #endif
459
460 /* Clean the media data. */
461 _fx_system_media_opened_ptr = FX_NULL;
462 _fx_system_media_opened_count = 0;
463
464 /* Clean the media. */
465 memset(media_ptr, 0, sizeof(FX_MEDIA));
466
467 /* Simulate poweroff. */
468 /* First terminate the thread to ensure it is ready for deletion. */
469 #ifndef FX_STANDALONE_ENABLE
470 tx_thread_terminate(&ftest_1);
471 #else
472 pthread_cancel(ptid1);
473 #endif
474 }
475
476 /* Return. */
477 return FX_SUCCESS;
478 }
479 #else
480
481 #ifdef CTEST
test_application_define(void * first_unused_memory)482 void test_application_define(void *first_unused_memory)
483 #else
484 void filex_fault_tolerant_write_large_data_interrupt_test_application_define(void *first_unused_memory)
485 #endif
486 {
487
488 FX_PARAMETER_NOT_USED(first_unused_memory);
489
490 /* Print out some test information banners. */
491 printf("FileX Test: Fault Tolerant Write Large Data Interrupt test.........N/A\n");
492
493 test_control_return(255);
494 }
495 #endif
496