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