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