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