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