00001 #ifndef RENDEZVOUS_IMPLEMENTATION_FILE
00002 #define RENDEZVOUS_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "filename.h"
00025 #include "rendezvous.h"
00026
00027 #include <basis/convert_utf.h>
00028 #include <basis/function.h>
00029 #include <basis/istring.h>
00030 #include <basis/log_base.h>
00031 #include <basis/portable.h>
00032
00033 #ifdef __UNIX__
00034 #include <stdio.h>
00035 #include <sys/stat.h>
00036 #endif
00037
00038
00039
00040
00041 #undef LOG
00042 #define LOG(tp) printf("%s%s\n", utility::timestamp(true, true).s(), istring(tp).s())
00043
00044
00045
00046
00047
00048 istring general_lock_name(const istring &root_part)
00049 { return root_part + "_app_lock"; }
00050
00051 #ifdef __UNIX__
00052
00053 istring unix_rendez_file(const istring &lock_name)
00054 {
00055 istring clean_name = lock_name;
00056
00057 filename::detooth_filename(clean_name);
00058
00059
00060
00061
00062
00063
00064 istring tmp_dir = "/tmp/rendezvous";
00065
00066 mkdir(tmp_dir.observe(), 0777);
00067 return tmp_dir + "/ren_" + clean_name;
00068 }
00069 #endif
00070
00071 rendezvous::rendezvous(const istring &root_name)
00072 : _handle(NIL),
00073 _locked(false),
00074 _root_name(new istring(root_name))
00075 {
00076 FUNCDEF("constructor");
00077 istring lock_name = general_lock_name(root_name);
00078 #ifdef __UNIX__
00079 istring real_name = unix_rendez_file(lock_name);
00080 FILE *locking_file = fopen(real_name.s(), "wb");
00081 if (!locking_file) {
00082 #ifdef DEBUG_RENDEZVOUS
00083 LOG(istring("failure to create locking file ") + real_name
00084 + ": " + portable::system_error_text(portable::system_error()) );
00085 #endif
00086 return;
00087 }
00088
00089 _handle = locking_file;
00090 #endif
00091 #ifdef __WIN32__
00092 _handle = CreateMutex(NIL, false, to_unicode_temp(lock_name));
00093 if (!_handle) return;
00094 #endif
00095 }
00096
00097 rendezvous::~rendezvous()
00098 {
00099 FUNCDEF("destructor");
00100 #ifdef DEBUG_RENDEZVOUS
00101 LOG("okay, into destructor for rendezvous.");
00102 #endif
00103 #ifdef __UNIX__
00104 if (_handle) {
00105 if (_locked) {
00106 int ret = lockf(fileno((FILE *)_handle), F_ULOCK, sizeof(int));
00107 if (ret) {
00108 #ifdef DEBUG_RENDEZVOUS
00109 LOG("failure to get lock on file.");
00110 #endif
00111 }
00112 _locked = false;
00113
00114
00115
00116
00117
00118
00119 }
00120
00121 fclose((FILE *)_handle);
00122 _handle = NIL;
00123 }
00124 #endif
00125 #ifdef __WIN32__
00126 if (_handle) CloseHandle((HANDLE)_handle);
00127 #endif
00128 WHACK(_root_name);
00129 }
00130
00131 void rendezvous::establish_lock() { lock(); }
00132
00133 void rendezvous::repeal_lock() { unlock(); }
00134
00135 bool rendezvous::healthy() const
00136 {
00137 return !!_handle;
00138 }
00139
00140 bool rendezvous::lock(locking_methods how)
00141 {
00142 FUNCDEF("lock");
00143 if (how == NO_LOCKING) return false;
00144 if (!healthy()) return false;
00145 #ifdef __UNIX__
00146 int command = F_TLOCK;
00147 if (how == ENDLESS_WAIT) command = F_LOCK;
00148 int ret = lockf(fileno((FILE *)_handle), command, sizeof(int));
00149 if (ret) {
00150 #ifdef DEBUG_RENDEZVOUS
00151 LOG("failure to get lock on file.");
00152 #endif
00153 return false;
00154 }
00155 #ifdef DEBUG_RENDEZVOUS
00156 LOG("okay, got lock on shared mem.");
00157 #endif
00158 _locked = true;
00159 return true;
00160 #endif
00161 #ifdef __WIN32__
00162 int timing = 0;
00163 if (how == ENDLESS_WAIT) timing = INFINITE;
00164 int ret = WaitForSingleObject((HANDLE)_handle, timing);
00165 if ( (ret == WAIT_ABANDONED) || (ret == WAIT_TIMEOUT) ) return false;
00166 else if (ret != WAIT_OBJECT_0) {
00167 #ifdef DEBUG_RENDEZVOUS
00168 LOG("got an unanticipated error from waiting for the mutex.");
00169 #endif
00170 return false;
00171 }
00172 _locked = true;
00173 return true;
00174 #endif
00175 return false;
00176 }
00177
00178 void rendezvous::unlock()
00179 {
00180 FUNCDEF("unlock");
00181 if (!healthy()) return;
00182 if (_locked) {
00183 #ifdef __UNIX__
00184 int ret = lockf(fileno((FILE *)_handle), F_ULOCK, sizeof(int));
00185 if (ret) {
00186 #ifdef DEBUG_RENDEZVOUS
00187 LOG("failure to get lock on file.");
00188 #endif
00189 }
00190 #endif
00191 #ifdef __WIN32__
00192 ReleaseMutex((HANDLE)_handle);
00193 #endif
00194 _locked = false;
00195 } else {
00196 #ifdef DEBUG_RENDEZVOUS
00197 LOG("okay, rendezvous wasn't locked.");
00198 #endif
00199 }
00200 }
00201
00202
00203 #endif //RENDEZVOUS_IMPLEMENTATION_FILE
00204