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