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