1 module during.tests.fsync;
2 
3 import during;
4 import during.tests.base;
5 
6 import core.stdc.stdlib;
7 import core.sys.linux.errno;
8 import core.sys.linux.fcntl;
9 import core.sys.posix.sys.uio : iovec;
10 import core.sys.posix.unistd;
11 
12 @("single")
13 unittest
14 {
15     Uring io;
16     auto res = io.setup();
17     assert(res >= 0, "Error initializing IO");
18 
19     auto fname = getTestFileName!"fsync_single";
20     auto fd = openFile(fname, O_CREAT | O_WRONLY);
21     scope (exit) unlink(&fname[0]);
22 
23     auto ret = io
24         .putWith!((ref SubmissionEntry e, int fd) => e.prepFsync(fd))(fd)
25         .submit(1);
26     assert(ret == 1);
27     assert(io.length == 1);
28     assert(io.front.res == 0);
29     io.popFront();
30 
31     close(fd);
32 }
33 
34 @("barier")
35 unittest
36 {
37     enum NUM_WRITES = 4;
38     Uring io;
39     auto res = io.setup();
40     assert(res >= 0, "Error initializing IO");
41 
42     auto fname = getTestFileName!"fsync_barier";
43     auto fd = openFile(fname, O_CREAT | O_WRONLY);
44     scope (exit) unlink(&fname[0]);
45 
46     iovec[4] iovecs;
47     foreach (i; 0..NUM_WRITES)
48     {
49         iovecs[i].iov_base = malloc(4096);
50         iovecs[i].iov_len = 4096;
51     }
52 
53     int off;
54     foreach (i; 0..NUM_WRITES)
55     {
56         io.putWith!((ref SubmissionEntry e, int fd, ref iovec v, int off)
57         {
58             e.prepWritev(fd, v, off);
59             e.user_data = 1;
60         })(fd, iovecs[i], off);
61         off += 4096;
62     }
63 
64     io.putWith!((ref SubmissionEntry e, int fd)
65     {
66         e.prepFsync(fd);//, FsyncFlags.DATASYNC);
67         e.user_data = 2;
68         // TODO: Works with IO_LINK but not without it: See: https://github.com/axboe/liburing/issues/33
69         e.flags = cast(SubmissionEntryFlags)(SubmissionEntryFlags.IO_DRAIN | SubmissionEntryFlags.IO_LINK);
70         // e.flags = SubmissionEntryFlags.IO_DRAIN;
71     })(fd);
72 
73     auto ret = io.submit(NUM_WRITES + 1);
74     if (ret < 0)
75     {
76         if (ret == -EINVAL)
77         {
78             version (D_BetterC)
79             {
80                 errmsg = "kernel may not support barrier fsync yet";
81                 return;
82             }
83             else throw new Exception("kernel may not support barrier fsync yet");
84         }
85         assert(0, "submit failed");
86     }
87     else assert(ret == NUM_WRITES + 1);
88 
89     assert(io.length == NUM_WRITES + 1);
90     foreach (i; 0..NUM_WRITES + 1)
91     {
92         if (io.front.res == -EINVAL)
93         {
94             version (D_BetterC)
95             {
96                 errmsg = "kernel doesn't support IOSQE_IO_DRAIN";
97                 break;
98             }
99             else throw new Exception("kernel doesn't support IOSQE_IO_DRAIN");
100         }
101         assert(io.front.res >= 0);
102         if (i < NUM_WRITES) assert(io.front.user_data == 1, "unexpected op completion");
103         else assert(io.front.user_data == 2, "unexpected op completion");
104 
105         io.popFront();
106     }
107 
108     close(fd);
109 }
110 
111 @("range")
112 unittest
113 {
114     version (D_BetterC) errmsg = "Not implemented";
115     else throw new Exception("Not implemented");
116 }