1 /* This FileX test concentrates on the Fault-Tolerant redo log write interrupt operation.
2  * The available bytes before/after file write should be decreased write_buffer_size only. */
3 
4 #ifndef FX_STANDALONE_ENABLE
5 #include   "tx_api.h"
6 #else
7 #define    _GNU_SOURCE
8 #define    _DEFAULT_SOURCE
9 #include   <pthread.h>
10 #include   <unistd.h>
11 #endif
12 #include   "fx_api.h"
13 #include   "fx_system.h"
14 #include   "fx_fault_tolerant.h"
15 #include   <stdio.h>
16 #include   "fx_ram_driver_test.h"
17 extern void    test_control_return(UINT status);
18 void    filex_fault_tolerant_file_write_available_test_application_define(void *first_unused_memory);
19 
20 #if defined (FX_ENABLE_FAULT_TOLERANT) && defined (FX_FAULT_TOLERANT) && defined (FX_FAULT_TOLERANT_DATA)
21 
22 #define     DEMO_STACK_SIZE         4096
23 #define CACHE_SIZE                  2048
24 #define FAULT_TOLERANT_SIZE         FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
25 
26 
27 
28 
29 /* Define the ThreadX and FileX object control blocks...  */
30 
31 #ifndef FX_STANDALONE_ENABLE
32 static TX_THREAD                ftest_0;
33 static TX_THREAD                ftest_1;
34 #else
35 static pthread_t                ptid1;
36 #endif
37 static FX_MEDIA                 ram_disk;
38 static FX_FILE                  my_file;
39 static UCHAR                    *pointer;
40 
41 /* Define the counters used in the test application...  */
42 
43 #ifndef FX_STANDALONE_ENABLE
44 static UCHAR                    *cache_buffer;
45 static UCHAR                    *fault_tolerant_buffer;
46 static UCHAR                    *thread_buffer;
47 #else
48 static UCHAR                    cache_buffer[CACHE_SIZE];
49 static UCHAR                    fault_tolerant_buffer[FAULT_TOLERANT_SIZE];
50 #endif
51 static UINT                     error_couter = 0;
52 static UINT                     log_write_interrupt = FX_FALSE;
53 static UINT                     write_index;
54 static UINT                     i;
55 
56 static CHAR                         write_buffer[2048];
57 static UINT                         write_buffer_size = 2048;
58 static CHAR                         read_buffer[4096];
59 static UINT                         read_buffer_size = 4096;
60 
61 #define SEEK_COUNT              5
62 #define FAT_COUNT               3            /* FAT12, 16, 32.  */
63 #define TEST_COUNT              FAT_COUNT * SEEK_COUNT
64 
65 /* Define thread prototypes.  */
66 
67 static void    ftest_0_entry(ULONG thread_input);
68 #ifndef FX_STANDALONE_ENABLE
69 static void    ftest_1_entry(ULONG thread_input);
70 #else
71 static void    *ftest_1_entry(void * thread_input);
72 #endif
73 extern void    _fx_ram_driver(FX_MEDIA *media_ptr);
74 extern void    test_control_return(UINT status);
75 extern UINT    _filex_fault_tolerant_log_check(FX_MEDIA *media_ptr);
76 extern UINT    (*driver_write_callback)(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr);
77 static UINT    my_driver_write(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr);
78 
79 
80 
81 /* Define what the initial system looks like.  */
82 
83 #ifdef CTEST
test_application_define(void * first_unused_memory)84 void test_application_define(void *first_unused_memory)
85 #else
86 void    filex_fault_tolerant_file_write_available_test_application_define(void *first_unused_memory)
87 #endif
88 {
89 
90 
91 #ifndef FX_STANDALONE_ENABLE
92     /* Setup the working pointer.  */
93     pointer =  (UCHAR *) first_unused_memory;
94 
95     /* Create the main thread.  */
96     tx_thread_create(&ftest_0, "thread 0", ftest_0_entry, 0,
97             pointer, DEMO_STACK_SIZE,
98             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
99     pointer =  pointer + DEMO_STACK_SIZE;
100 
101     /* Setup memory for the RAM disk and the sector cache.  */
102     cache_buffer =  pointer;
103     pointer += CACHE_SIZE;
104     fault_tolerant_buffer = pointer;
105     pointer += FAULT_TOLERANT_SIZE;
106     thread_buffer = pointer;
107     pointer += DEMO_STACK_SIZE;
108 #endif
109 
110     /* Initialize the FileX system.  */
111     fx_system_initialize();
112 #ifdef FX_STANDALONE_ENABLE
113     ftest_0_entry(0);
114 #endif
115 }
116 
117 
118 
119 /* Define the test threads.  */
120 
ftest_0_entry(ULONG thread_input)121 static void    ftest_0_entry(ULONG thread_input)
122 {
123 
124 UINT        status;
125 ULONG       actual;
126 ULONG64     available_bytes_before_write;
127 ULONG64     available_bytes_after_write;
128 
129     FX_PARAMETER_NOT_USED(thread_input);
130 
131     /* Print out some test information banners.  */
132     printf("FileX Test:   Fault Tolerant File Write Available Test...............");
133 
134     /* Loop to test FAT 12, 16, 32.   */
135     for (i = 0; i < TEST_COUNT; i ++)
136     {
137         if (i < 5)
138         {
139             /* Format the media with FAT12.  This needs to be done before opening it!  */
140             status =  fx_media_format(&ram_disk,
141                                      _fx_ram_driver,         // Driver entry
142                                      ram_disk_memory_large,  // RAM disk memory pointer
143                                      cache_buffer,           // Media buffer pointer
144                                      CACHE_SIZE,             // Media buffer size
145                                      "MY_RAM_DISK",          // Volume Name
146                                      1,                      // Number of FATs
147                                      32,                     // Directory Entries
148                                      0,                      // Hidden sectors
149                                      256,                    // Total sectors
150                                      256,                    // Sector size
151                                      8,                      // Sectors per cluster
152                                      1,                      // Heads
153                                      1);                     // Sectors per track
154         }
155         else if (i < 10)
156         {
157             /* Format the media with FAT16.  This needs to be done before opening it!  */
158             status =  fx_media_format(&ram_disk,
159                                      _fx_ram_driver,         // Driver entry
160                                      ram_disk_memory_large,  // RAM disk memory pointer
161                                      cache_buffer,           // Media buffer pointer
162                                      CACHE_SIZE,             // Media buffer size
163                                      "MY_RAM_DISK",          // Volume Name
164                                      1,                      // Number of FATs
165                                      32,                     // Directory Entries
166                                      0,                      // Hidden sectors
167                                      4200 * 8,               // Total sectors
168                                      256,                    // Sector size
169                                      8,                      // Sectors per cluster
170                                      1,                      // Heads
171                                      1);                     // Sectors per track
172         }
173         else if (i < 15)
174         {
175             /* Format the media with FAT32.  This needs to be done before opening it!  */
176             status =  fx_media_format(&ram_disk,
177                                      _fx_ram_driver,         // Driver entry
178                                      ram_disk_memory_large,  // RAM disk memory pointer
179                                      cache_buffer,           // Media buffer pointer
180                                      CACHE_SIZE,             // Media buffer size
181                                      "MY_RAM_DISK",          // Volume Name
182                                      1,                      // Number of FATs
183                                      32,                     // Directory Entries
184                                      0,                      // Hidden sectors
185                                      70000 * 4,              // Total sectors
186                                      512,                    // Sector size
187                                      4,                      // Sectors per cluster
188                                      1,                      // Heads
189                                      1);                     // Sectors per track
190         }
191 
192         /* Determine if the format had an error.  */
193         if (status)
194         {
195 
196             printf("ERROR!\n");
197             test_control_return(1);
198         }
199 
200         /* Open the ram_disk.  */
201         status =  fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
202 
203         /* Check the status.  */
204         if (status != FX_SUCCESS)
205         {
206 
207             /* Error, return error code.  */
208             printf("ERROR!\n");
209             test_control_return(2);
210         }
211 
212         /* Get available bytes before write. */
213         fx_media_extended_space_available(&ram_disk, &available_bytes_before_write);
214 
215         /* Enable the Fault-tolerant feature.  */
216         status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
217 
218         /* Check status.   */
219         if (status)
220         {
221 
222             printf("ERROR!\n");
223             test_control_return(3);
224         }
225 
226         /* Get available bytes before write. */
227         fx_media_extended_space_available(&ram_disk, &available_bytes_after_write);
228         if (available_bytes_before_write != (available_bytes_after_write +
229                     ram_disk.fx_media_fault_tolerant_clusters * ram_disk.fx_media_bytes_per_sector * ram_disk.fx_media_sectors_per_cluster))
230         {
231 
232             printf("ERROR!\n");
233             test_control_return(38);
234         }
235 
236         /* Create a file called TEST.TXT in the root directory.  */
237         status =  fx_file_create(&ram_disk, "TEST.TXT");
238 
239         /* Check the create status.  */
240         if (status != FX_SUCCESS)
241         {
242 
243             printf("ERROR!\n");
244             test_control_return(4);
245         }
246 
247         /* Open the test file.  */
248         status =  fx_file_open(&ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
249 
250         /* Check the file open status.  */
251         if (status != FX_SUCCESS)
252         {
253 
254             printf("ERROR!\n");
255             test_control_return(5);
256         }
257 
258         /* Get available bytes before write. */
259         fx_media_extended_space_available(&ram_disk, &available_bytes_before_write);
260 
261         /* Write a string to the test file.  */
262         status =  fx_file_write(&my_file, " ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 28);
263 
264         /* Check the file write status.  */
265         if (status != FX_SUCCESS)
266         {
267 
268             printf("ERROR!\n");
269             test_control_return(6);
270         }
271 
272         /* Get available bytes after write. */
273         fx_media_extended_space_available(&ram_disk, &available_bytes_after_write);
274         {
275             if ((available_bytes_before_write - available_bytes_after_write) != 2048)
276             {
277 
278                 printf("ERROR!\n");
279                 test_control_return(37);
280             }
281         }
282 
283         /* Seek to the beginning of the test file.  */
284         status =  fx_file_seek(&my_file, 0);
285 
286         /* Check the file seek status.  */
287         if (status != FX_SUCCESS)
288         {
289 
290             printf("ERROR!\n");
291             test_control_return(7);
292         }
293 
294         /* Read the bytes of the test file.  */
295         status =  fx_file_read(&my_file, read_buffer, read_buffer_size, &actual);
296 
297         /* Check the file read status.  */
298         if ((status != FX_SUCCESS) || (actual != 28))
299         {
300 
301             printf("ERROR!\n");
302             test_control_return(8);
303         }
304 
305         /* Close the test file.  */
306         status =  fx_file_close(&my_file);
307 
308         /* Check the file close status.  */
309         if (status != FX_SUCCESS)
310         {
311 
312             printf("ERROR!\n");
313             test_control_return(9);
314         }
315 
316         /* Create a file called TEST1.TXT in the root directory.  */
317         status =  fx_file_create(&ram_disk, "TEST1.TXT");
318 
319         /* Check the create status.  */
320         if (status != FX_SUCCESS)
321         {
322 
323             printf("ERROR!\n");
324             test_control_return(10);
325         }
326 
327         /* Get available bytes before write. */
328         fx_media_extended_space_available(&ram_disk, &available_bytes_before_write);
329 
330 #ifndef FX_STANDALONE_ENABLE
331         /* Create the main thread.  */
332         tx_thread_create(&ftest_1, "thread 1", ftest_1_entry, 0,
333                         thread_buffer, DEMO_STACK_SIZE,
334                         4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
335 #endif
336         /* directory_write_interrupt */
337         log_write_interrupt = FX_FALSE;
338 
339         /* Let the other thread run.  */
340 #ifndef FX_STANDALONE_ENABLE
341         tx_thread_relinquish();
342 #else
343         pthread_create(&ptid1, NULL, &ftest_1_entry, NULL);
344         usleep(10);
345         pthread_join(ptid1,NULL);
346 #endif
347 
348         /* After write interrupt, reread the files.  */
349 
350         /* Open the ram_disk.  */
351         status =  fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
352 
353         /* Check the status.  */
354         if (status != FX_SUCCESS)
355         {
356 
357             /* Error, return error code.  */
358             printf("ERROR!\n");
359             test_control_return(22);
360         }
361 
362         /* Enable the Fault-tolerant feature to recover the media.  */
363         status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
364 
365         /* Check status.   */
366         if (status)
367         {
368 
369             printf("ERROR!\n");
370             test_control_return(23);
371         }
372 
373         /* Get available bytes after write. */
374         fx_media_extended_space_available(&ram_disk, &available_bytes_after_write);
375         {
376             if ((available_bytes_before_write - available_bytes_after_write) != 2048)
377             {
378 
379                 printf("ERROR!\n");
380                 test_control_return(37);
381             }
382         }
383 
384         /* Open the test file.  */
385         status =  fx_file_open(&ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
386 
387         /* Check the file open status.  */
388         if (status != FX_SUCCESS)
389         {
390 
391             printf("ERROR!\n");
392             test_control_return(24);
393         }
394 
395         /* Seek to the beginning of the test file.  */
396         status =  fx_file_seek(&my_file, 0);
397 
398         /* Check the file seek status.  */
399         if (status != FX_SUCCESS)
400         {
401 
402             printf("ERROR!\n");
403             test_control_return(25);
404         }
405 
406         /* Read the bytes of the test file.  */
407         status =  fx_file_read(&my_file, read_buffer, read_buffer_size, &actual);
408 
409         /* Check the file read status.  */
410         if ((status != FX_SUCCESS) || (actual != 28))
411         {
412 
413             printf("ERROR!\n");
414             test_control_return(26);
415         }
416 
417         /* Close the test file.  */
418         status =  fx_file_close(&my_file);
419 
420         /* Check the file close status.  */
421         if (status != FX_SUCCESS)
422         {
423 
424             printf("ERROR!\n");
425             test_control_return(27);
426         }
427 
428         /* Open the test file.  */
429         status =  fx_file_open(&ram_disk, &my_file, "TEST1.TXT", FX_OPEN_FOR_WRITE);
430 
431         /* Check the file open status.  */
432         if (status != FX_SUCCESS)
433         {
434 
435             printf("ERROR!\n");
436             test_control_return(28);
437         }
438 
439         /* Seek to the beginning of the test file.  */
440         status =  fx_file_seek(&my_file, 0);
441 
442         /* Check the file seek status.  */
443         if (status != FX_SUCCESS)
444         {
445 
446             printf("ERROR!\n");
447             test_control_return(29);
448         }
449 
450         /* Read the bytes of the test file.  */
451         status =  fx_file_read(&my_file, read_buffer, read_buffer_size, &actual);
452 
453         /* Check the file read status. FAT 12, 16, 32.  */
454         if ((status != FX_SUCCESS) || (actual != write_buffer_size) || memcmp(read_buffer, write_buffer, actual))
455         {
456 
457             printf("ERROR!\n");
458             test_control_return(30);
459         }
460 
461         /* Close the test file.  */
462         status =  fx_file_close(&my_file);
463 
464         /* Check the file close status.  */
465         if (status != FX_SUCCESS)
466         {
467 
468             printf("ERROR!\n");
469             test_control_return(31);
470         }
471 
472         /* Close the media.  */
473         status =  fx_media_close(&ram_disk);
474 
475         /* Determine if the test was successful.  */
476         if ((status != FX_SUCCESS) || (log_write_interrupt != FX_TRUE) || (error_couter))
477         {
478 
479             printf("ERROR!\n");
480             test_control_return(36);
481         }
482 
483         /* Delete the thread.  */
484 #ifndef FX_STANDALONE_ENABLE
485         tx_thread_delete(&ftest_1);
486 #else
487         pthread_cancel(ptid1);
488 #endif
489     }
490 
491     /* Output successful.  */
492     printf("SUCCESS!\n");
493     test_control_return(0);
494 }
495 
496 /* Define the test threads.  */
497 
498 #ifndef FX_STANDALONE_ENABLE
ftest_1_entry(ULONG thread_input)499 static void    ftest_1_entry(ULONG thread_input)
500 #else
501  void  *  ftest_1_entry(void * thread_input)
502 #endif
503 {
504 
505 #ifdef FX_STANDALONE_ENABLE
506     UINT oldtype;
507     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
508     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
509 #endif
510 
511 UINT        status;
512 
513     FX_PARAMETER_NOT_USED(thread_input);
514 
515     /* Set the callback function to simulate poweoff operation when write FAT entry.  */
516     driver_write_callback = my_driver_write;
517 
518     /* Open the test file.  */
519     status =  fx_file_open(&ram_disk, &my_file, "TEST1.TXT", FX_OPEN_FOR_WRITE);
520 
521     /* Check the file open status.  */
522     if (status != FX_SUCCESS)
523     {
524         error_couter ++;
525 #ifndef FX_STANDALONE_ENABLE
526         return;
527 #else
528         return NULL;
529 #endif
530     }
531 
532     /* Random genearte the write data.  */
533     for (write_index = 0; write_index < write_buffer_size; write_index ++)
534     {
535         write_buffer[write_index] = (CHAR)rand();
536     }
537 
538     /* Write 1024 bytes to the file, then update the FAT table.  (bytes should be greate than one cluster).  */
539     fx_file_write(&my_file, (void *) write_buffer, write_buffer_size);
540 }
541 
my_driver_write(FX_MEDIA * media_ptr,UINT sector_type,UCHAR * block_ptr,UINT * operation_ptr)542 static UINT my_driver_write(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr)
543 {
544 
545     FX_PARAMETER_NOT_USED(block_ptr);
546 
547     /* Interrupt the redo log write operation.  */
548     if ((sector_type == FX_DATA_SECTOR) && (_filex_fault_tolerant_log_check(media_ptr) & FX_FAULT_TOLERANT_LOG_REDO_DONE))
549     {
550 
551         /* Set the write interrupt operation.  */
552         *operation_ptr = FX_OP_WRITE_INTERRUPT;
553 
554         /* Update the flag.  */
555         log_write_interrupt = FX_TRUE;
556 
557         /* Clean the callback function.  */
558         driver_write_callback = FX_NULL;
559 
560         /* Delete the media protection structure if FX_SINGLE_THREAD is not
561         defined.  */
562 #ifndef FX_SINGLE_THREAD
563 #ifndef FX_DONT_CREATE_MUTEX
564 
565         /* Note that the protection is never released. The mutex delete
566         service will handle all threads waiting access to this media
567         control block.  */
568         tx_mutex_delete(&(media_ptr -> fx_media_protect));
569 #endif
570 #endif
571 
572         /* Clean the media data.  */
573         _fx_system_media_opened_ptr = FX_NULL;
574         _fx_system_media_opened_count = 0;
575 
576         /* Clean the media.  */
577         memset(media_ptr, 0, sizeof(FX_MEDIA));
578 
579         /* Simulate poweroff.  */
580         /* First terminate the thread to ensure it is ready for deletion.  */
581 #ifndef FX_STANDALONE_ENABLE
582         tx_thread_terminate(&ftest_1);
583 #else
584         pthread_cancel(ptid1);
585 #endif
586     }
587 
588     /* Return.  */
589     return FX_SUCCESS;
590 }
591 
592 #else
593 
594 #ifdef CTEST
test_application_define(void * first_unused_memory)595 void test_application_define(void *first_unused_memory)
596 #else
597 void    filex_fault_tolerant_file_write_available_test_application_define(void *first_unused_memory)
598 #endif
599 {
600 
601     FX_PARAMETER_NOT_USED(first_unused_memory);
602 
603     /* Print out some test information banners.  */
604     printf("FileX Test:   Fault Tolerant File Write Available Test...............N/A\n");
605 
606     test_control_return(255);
607 }
608 #endif
609 
610