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