1 #ifndef FX_STANDALONE_ENABLE
2 #include   "tx_api.h"
3 #else
4 #define    _GNU_SOURCE
5 #define    _DEFAULT_SOURCE
6 #include   <pthread.h>
7 #include   <unistd.h>
8 #endif
9 #include   "fx_api.h"
10 #include   "fx_system.h"
11 #include   "fx_fault_tolerant.h"
12 #include   <stdio.h>
13 #include   "fx_ram_driver_test.h"
14 extern void    test_control_return(UINT status);
15 void    filex_fault_tolerant_recover_fail_test_application_define(void *first_unused_memory);
16 
17 #if defined (FX_ENABLE_FAULT_TOLERANT) && defined (FX_FAULT_TOLERANT) && defined (FX_FAULT_TOLERANT_DATA)
18 
19 #define DEMO_STACK_SIZE         4096
20 #define CACHE_SIZE              2048
21 #define FAULT_TOLERANT_SIZE     FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
22 
23 
24 /* Define the ThreadX and FileX object control blocks...  */
25 
26 #ifndef FX_STANDALONE_ENABLE
27 static TX_THREAD                ftest_0;
28 static TX_THREAD                ftest_1;
29 #else
30 static pthread_t                ptid1;
31 #endif
32 static FX_MEDIA                 ram_disk;
33 static FX_FILE                  my_file;
34 static UCHAR                    *pointer;
35 
36 /* Define the counters used in the test application...  */
37 
38 #ifndef FX_STANDALONE_ENABLE
39 static UCHAR                    *cache_buffer;
40 static UCHAR                    *fault_tolerant_buffer;
41 static UCHAR                    *thread_buffer;
42 #else
43 static UCHAR                    cache_buffer[CACHE_SIZE];
44 static UCHAR                    fault_tolerant_buffer[FAULT_TOLERANT_SIZE];
45 #endif
46 
47 static UINT                     error_couter = 0;
48 static UINT                     data_write_interrupt = FX_FALSE;
49 static CHAR                     write_buffer[2048];
50 static UINT                     write_buffer_size = 2048;
51 static UINT                     write_index;
52 static CHAR                     read_buffer[4096];
53 static UINT                     read_buffer_size = 4096;
54 static UINT                     data_size = 0;
55 
56 #define SEEK_COUNT              5
57 #define FAT_COUNT               3            /* FAT12, 16, 32.  */
58 #define TEST_COUNT              FAT_COUNT * SEEK_COUNT
59 
60 /* Define thread prototypes.  */
61 
62 static void    ftest_0_entry(ULONG thread_input);
63 #ifndef FX_STANDALONE_ENABLE
64 static void    ftest_1_entry(ULONG thread_input);
65 #else
66 static void   * ftest_1_entry(void * thread_input);
67 #endif
68 extern void    _fx_ram_driver(FX_MEDIA *media_ptr);
69 extern void    test_control_return(UINT status);
70 extern UINT    _filex_fault_tolerant_log_check(FX_MEDIA *media_ptr);
71 extern UINT    (*driver_write_callback)(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr);
72 static UINT    my_driver_write(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr);
73 
74 
75 
76 /* Define what the initial system looks like.  */
77 
78 #ifdef CTEST
test_application_define(void * first_unused_memory)79 void test_application_define(void *first_unused_memory)
80 #else
81 void    filex_fault_tolerant_recover_fail_test_application_define(void *first_unused_memory)
82 #endif
83 {
84 
85 
86 #ifndef FX_STANDALONE_ENABLE
87     /* Setup the working pointer.  */
88     pointer =  (UCHAR *) first_unused_memory;
89 
90     /* Create the main thread.  */
91 
92     tx_thread_create(&ftest_0, "thread 0", ftest_0_entry, 0,
93             pointer, DEMO_STACK_SIZE,
94             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
95 
96     pointer =  pointer + DEMO_STACK_SIZE;
97 
98     /* Setup memory for the RAM disk and the sector cache.  */
99     cache_buffer =  pointer;
100     pointer += CACHE_SIZE;
101     fault_tolerant_buffer = pointer;
102     pointer += FAULT_TOLERANT_SIZE;
103     thread_buffer = pointer;
104     pointer += DEMO_STACK_SIZE;
105 #endif
106 
107     /* Initialize the FileX system.  */
108     fx_system_initialize();
109 #ifdef FX_STANDALONE_ENABLE
110     ftest_0_entry(0);
111 #endif
112 }
113 
114 
115 
116 /* Define the test threads.  */
117 
ftest_0_entry(ULONG thread_input)118 static void    ftest_0_entry(ULONG thread_input)
119 {
120 
121 UINT        status;
122 ULONG       actual;
123 UINT        i;
124 
125     FX_PARAMETER_NOT_USED(thread_input);
126 
127     /* Print out some test information banners.  */
128     printf("FileX Test:   Fault tolerant recover fail test.......................");
129 
130     for (i = 1; i <= 2; i++)
131     {
132 
133         /* Format the media with FAT12.  This needs to be done before opening it!  */
134         status =  fx_media_format(&ram_disk,
135                                      _fx_ram_driver,         // Driver entry
136                                      ram_disk_memory_large,  // RAM disk memory pointer
137                                      cache_buffer,           // Media buffer pointer
138                                      CACHE_SIZE,             // Media buffer size
139                                      "MY_RAM_DISK",          // Volume Name
140                                      1,                      // Number of FATs
141                                      32,                     // Directory Entries
142                                      0,                      // Hidden sectors
143                                      256,                    // Total sectors
144                                      256,                    // Sector size
145                                      8,                      // Sectors per cluster
146                                      1,                      // Heads
147                                      1);                     // Sectors per track
148         return_if_fail( status == FX_SUCCESS);
149 
150         /* Open the ram_disk and enable fault_tolerant feature.  */
151         status += fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
152         status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
153         return_if_fail( status == FX_SUCCESS);
154 
155         /* Prepare a file for test. */
156         status = fx_file_create(&ram_disk, "TEST.TXT");
157         status += fx_file_open(&ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
158         status += fx_file_write(&my_file, " ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 28);
159         status += fx_file_seek(&my_file, 0);
160         return_if_fail( status == FX_SUCCESS);
161 
162         /* Read the bytes of the test file.  */
163         memset(read_buffer, 0, read_buffer_size);
164         status = fx_file_read(&my_file, read_buffer, read_buffer_size, &actual);
165         return_if_fail( (status == FX_SUCCESS) && (actual == 28));
166 
167         /* Close the test file.  */
168         status = fx_file_close(&my_file);
169         return_if_fail( status == FX_SUCCESS);
170 
171         /* Create a file called TEST1.TXT in the root directory.  */
172         status = fx_file_create(&ram_disk, "TEST1.TXT");
173         status += fx_file_open(&ram_disk, &my_file, "TEST1.TXT", FX_OPEN_FOR_WRITE);
174         return_if_fail( status == FX_SUCCESS);
175 
176         /* Write some data into file.  */
177         data_size = 1500;
178         status = fx_file_write(&my_file, (void *) write_buffer, data_size);
179         status += fx_file_seek(&my_file, 0);
180         return_if_fail( status == FX_SUCCESS);
181 
182         /* Read the bytes of the test file.  */
183         memset(read_buffer, 0, read_buffer_size);
184         status = fx_file_read(&my_file, read_buffer, read_buffer_size, &actual);
185         return_if_fail( (status == FX_SUCCESS) && (actual == data_size));
186 
187         /* Close the test file.  */
188         status = fx_file_close(&my_file);
189         return_if_fail( status == FX_SUCCESS);
190 
191         /* Create the main thread.  */
192 #ifndef FX_STANDALONE_ENABLE
193         tx_thread_create(&ftest_1, "thread 1", ftest_1_entry, 0,
194                         thread_buffer, DEMO_STACK_SIZE,
195                         4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
196 #endif
197 
198         /* directory_write_interrupt */
199         data_write_interrupt = FX_FALSE;
200 
201         /* Let the other thread run.  */
202 #ifndef FX_STANDALONE_ENABLE
203         tx_thread_relinquish();
204 #else
205         pthread_create(&ptid1, NULL, &ftest_1_entry, NULL);
206         usleep(10);
207         pthread_join(ptid1,NULL);
208 #endif
209 
210         /* After write interrupt, try to enable fault_tolerant again.  */
211 
212         /* Open the ram_disk.  */
213         status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory_large, cache_buffer, CACHE_SIZE);
214         return_if_fail( status == FX_SUCCESS);
215 
216         /* Enable the Fault-tolerant feature to recover the media. */
217         /* Make a mistake when fx_fault_tolerant_recover link original chain back to the front of the insertion point. */
218         _fx_utility_fat_entry_write_error_request = i;
219         status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
220         return_if_fail( status == FX_IO_ERROR);
221 
222         /* Close the media.  */
223         status =  fx_media_close(&ram_disk);
224         return_if_fail((status == FX_SUCCESS) && (data_write_interrupt == FX_TRUE) && (error_couter == 0));
225 
226         /* Delete the thread.  */
227 #ifndef FX_STANDALONE_ENABLE
228         tx_thread_delete(&ftest_1);
229 #else
230         pthread_cancel(ptid1);
231 #endif
232     }
233 
234     /* Output successful.  */
235     printf("SUCCESS!\n");
236     test_control_return(0);
237 }
238 
239 /* Define the test threads.  */
240 
241 #ifndef FX_STANDALONE_ENABLE
ftest_1_entry(ULONG thread_input)242 static void    ftest_1_entry(ULONG thread_input)
243 #else
244  void  *  ftest_1_entry(void * thread_input)
245 #endif
246 {
247 
248 #ifdef FX_STANDALONE_ENABLE
249     UINT oldtype;
250     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
251     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
252 #endif
253 
254 	UINT        status;
255 
256     FX_PARAMETER_NOT_USED(thread_input);
257 
258     /* Set the callback function to simulate poweoff operation when write FAT entry.  */
259     driver_write_callback = my_driver_write;
260 
261     /* Open the test file.  */
262     status =  fx_file_open(&ram_disk, &my_file, "TEST1.TXT", FX_OPEN_FOR_WRITE);
263 
264     /* Check the file open status.  */
265     if (status != FX_SUCCESS)
266     {
267         error_couter ++;
268 #ifndef FX_STANDALONE_ENABLE
269         return;
270 #else
271 	    return NULL;
272 #endif
273     }
274 
275     status = fx_file_seek(&my_file, 1500);
276 
277     /* Check the file seek status.  */
278     if (status != FX_SUCCESS)
279     {
280         error_couter ++;
281 #ifndef FX_STANDALONE_ENABLE
282         return;
283 #else
284 	    return NULL;
285 #endif
286     }
287 
288     /* Random genearte the write data.  */
289     for (write_index = 0; write_index < write_buffer_size; write_index ++)
290     {
291         write_buffer[write_index] = (CHAR)rand();
292     }
293 
294     /* Write 1024 bytes to the file, then update the FAT table.  (bytes should be greate than one cluster).  */
295     fx_file_write(&my_file, (void *) write_buffer, write_buffer_size);
296 }
297 
my_driver_write(FX_MEDIA * media_ptr,UINT sector_type,UCHAR * block_ptr,UINT * operation_ptr)298 static UINT my_driver_write(FX_MEDIA *media_ptr, UINT sector_type, UCHAR *block_ptr, UINT *operation_ptr)
299 {
300 
301     FX_PARAMETER_NOT_USED(block_ptr);
302 
303     /* Interrupt the Data write operation.  */
304     if ((sector_type == FX_DATA_SECTOR) && (_filex_fault_tolerant_log_check(media_ptr) & FX_FAULT_TOLERANT_LOG_UNDO_DONE))
305     {
306 
307         /* Set the write interrupt operation.  */
308         *operation_ptr = FX_OP_WRITE_INTERRUPT;
309 
310         /* Update the flag.  */
311         data_write_interrupt = FX_TRUE;
312 
313         /* Clean the callback function.  */
314         driver_write_callback = FX_NULL;
315 
316         /* Delete the media protection structure if FX_SINGLE_THREAD is not
317         defined.  */
318 #ifndef FX_SINGLE_THREAD
319 #ifndef FX_DONT_CREATE_MUTEX
320 
321         /* Note that the protection is never released. The mutex delete
322         service will handle all threads waiting access to this media
323         control block.  */
324         tx_mutex_delete(&(media_ptr -> fx_media_protect));
325 #endif
326 #endif
327 
328         /* Clean the media data.  */
329         _fx_system_media_opened_ptr = FX_NULL;
330         _fx_system_media_opened_count = 0;
331 
332         /* Clean the media.  */
333         memset(media_ptr, 0, sizeof(FX_MEDIA));
334 
335         /* Simulate poweroff.  */
336         /* First terminate the thread to ensure it is ready for deletion.  */
337 #ifndef FX_STANDALONE_ENABLE
338         tx_thread_terminate(&ftest_1);
339 #else
340         pthread_cancel(ptid1);
341 #endif
342     }
343 
344     /* Return.  */
345     return FX_SUCCESS;
346 }
347 #else
348 
349 #ifdef CTEST
test_application_define(void * first_unused_memory)350 void test_application_define(void *first_unused_memory)
351 #else
352 void    filex_fault_tolerant_recover_fail_test_application_define(void *first_unused_memory)
353 #endif
354 {
355 
356     FX_PARAMETER_NOT_USED(first_unused_memory);
357 
358     /* Print out some test information banners.  */
359     printf("FileX Test:   Fault tolerant recover fail test.......................N/A\n");
360 
361     test_control_return(255);
362 }
363 #endif
364 
365