00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "defs.h"
00022
00023 struct rec {
00024 int r_data;
00025 off_t r_next;
00026 };
00027
00028 bool readrec(int dbfd, struct rec *r, off_t off)
00029 {
00030 ssize_t nread;
00031
00032 if ((nread = pread(dbfd, r, sizeof(struct rec), off)) ==
00033 sizeof(struct rec))
00034 return true;
00035 if (nread != -1)
00036 errno = EIO;
00037 EC_FAIL
00038 return true;
00039
00040 EC_CLEANUP_BGN
00041 return false;
00042 EC_CLEANUP_END
00043 }
00044
00045 bool writerec(int dbfd, struct rec *r, off_t off)
00046 {
00047 ssize_t nwrote;
00048
00049 if ((nwrote = pwrite(dbfd, r, sizeof(struct rec), off)) ==
00050 sizeof(struct rec))
00051 return true;
00052 if (nwrote != -1)
00053 errno = EIO;
00054 EC_FAIL
00055 return true;
00056
00057 EC_CLEANUP_BGN
00058 return false;
00059 EC_CLEANUP_END
00060 }
00061
00062 bool store(int dbfd, int data)
00063 {
00064 struct rec r, rnew;
00065 off_t end, prev;
00066
00067 ec_neg1( end = lseek(dbfd, 0, SEEK_END) )
00068 prev = 0;
00069 ec_false( readrec(dbfd, &r, prev) )
00070 while (r.r_next != 0) {
00071 ec_false( readrec(dbfd, &r, r.r_next) )
00072 if (r.r_data > data)
00073 break;
00074 prev = r.r_next;
00075 }
00076 ec_false( readrec(dbfd, &r, prev) )
00077 rnew.r_next = r.r_next;
00078 r.r_next = end;
00079 ec_false( writerec(dbfd, &r, prev) )
00080 rnew.r_data = data;
00081 usleep(1);
00082 ec_false( writerec(dbfd, &rnew, end) )
00083 return true;
00084
00085 EC_CLEANUP_BGN
00086 return false;
00087 EC_CLEANUP_END
00088 }
00089
00090 #define DBNAME "termdb"
00091
00092 static void process1(void)
00093 {
00094 int dbfd, data;
00095 struct rec r;
00096
00097 ec_neg1( dbfd = open(DBNAME, O_CREAT | O_TRUNC | O_RDWR, PERM_FILE) )
00098 memset(&r, 0, sizeof(r));
00099 ec_false( writerec(dbfd, &r, 0) )
00100 for (data = 100; data >= 0; data--)
00101 ec_false( store(dbfd, data) )
00102 ec_neg1( close(dbfd) )
00103 exit(EXIT_SUCCESS);
00104
00105 EC_CLEANUP_BGN
00106 exit(EXIT_FAILURE);
00107 EC_CLEANUP_END
00108 }
00109
00110 static void process2(void)
00111 {
00112 int try, dbfd;
00113 struct rec r1, r2;
00114
00115 for (try = 0; try < 10; try++)
00116 if ((dbfd = open(DBNAME, O_RDWR)) == -1) {
00117 if (errno == ENOENT) {
00118 continue;
00119 }
00120 else
00121 EC_FAIL
00122 }
00123 ec_neg1( dbfd )
00124 for (try = 0; try < 100; try++) {
00125 ec_false( readrec(dbfd, &r1, 0) )
00126 while (r1.r_next != 0) {
00127 ec_false( readrec(dbfd, &r2, r1.r_next) )
00128 if (r1.r_data > r2.r_data) {
00129 printf("Found sorting error (try %d)\n", try);
00130 break;
00131 }
00132 r1 = r2;
00133 }
00134 }
00135 ec_neg1( close(dbfd) )
00136 return;
00137
00138 EC_CLEANUP_BGN
00139 exit(EXIT_FAILURE);
00140 EC_CLEANUP_END
00141 }
00142
00143 int main(void)
00144 {
00145 pid_t pid;
00146
00147 ec_neg1( pid = fork() )
00148 if (pid == 0)
00149 process1();
00150 else {
00151 process2();
00152 ec_neg1( waitpid(pid, NULL, 0) )
00153 }
00154 exit(EXIT_SUCCESS);
00155
00156 EC_CLEANUP_BGN
00157 exit(EXIT_FAILURE);
00158 EC_CLEANUP_END
00159 }
00160