Changeset 895 for trunk/server/lib/tdb/common/lock.c
- Timestamp:
- Mar 18, 2016, 7:53:30 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server/lib/tdb/common/lock.c
r878 r895 33 33 } 34 34 35 #ifdef __OS2__ 36 enum os2_fl { 37 OS2_FL_LOCK = 0x1, 38 OS2_FL_RW = 0x2, 39 OS2_FL_WAIT = 0x4, 40 OS2_FL_UPGRADE = 0x8, 41 }; 42 43 static int os2_set_file_locks(struct tdb_context *tdb, enum os2_fl flags, 44 off_t start, off_t offset, off_t len) 45 { 46 FILELOCKL locks[2] = {0}; 47 ULONG fl; 48 BOOL dowait; 49 APIRET arc; 50 51 if ((!(flags & OS2_FL_UPGRADE) && (start > offset || start < 0)) || 52 offset < 0 || offset + len < 0) { 53 errno = EINVAL; 54 return -1; 55 } 56 57 fl = (flags & OS2_FL_RW) ? 0 : 1; /* excluive when rw, shared otherwise */ 58 59 if (flags & OS2_FL_UPGRADE) { 60 locks[0].lOffset = offset; 61 locks[0].lRange = len == 0 ? OFF_MAX : len; 62 locks[1] = locks[0]; 63 fl |= 2; /* atomic */ 64 } else { 65 if (start != offset) { 66 locks[0].lOffset = start; 67 locks[0].lRange = offset - start; 68 fl |= 2; /* atomic */ 69 } 70 locks[1].lOffset = start; 71 locks[1].lRange = len == 0 ? OFF_MAX : (locks[0].lRange + len); 72 } 73 74 dowait = (flags & (OS2_FL_LOCK | OS2_FL_UPGRADE)) && (flags & OS2_FL_WAIT); 75 76 TDB_LOG((tdb, TDB_DEBUG_TRACE, "os2_file_locks: fd=%d lock_fd=%d flags=%x start=%lld offset=%lld len=%lld pid=%d\n", 77 tdb->fd, tdb->lock_fd, flags, start, offset, len, getpid())); 78 79 arc = DosSetFileLocksL(tdb->lock_fd, 80 &locks[(flags & OS2_FL_LOCK) ? 0 : 1], 81 &locks[(flags & OS2_FL_LOCK) ? 1 : 0], 82 dowait ? SEM_INDEFINITE_WAIT : SEM_IMMEDIATE_RETURN, 83 fl); 84 85 TDB_LOG((tdb, TDB_DEBUG_TRACE, "os2_file_locks: arc=%d pid=%d\n", arc, getpid())); 86 87 if (arc) { 88 switch (arc) { 89 case ERROR_LOCK_VIOLATION: 90 errno = EACCES; 91 break; 92 case ERROR_INTERRUPT: 93 errno = EINTR; 94 break; 95 case ERROR_TIMEOUT: 96 errno = EDEADLK; 97 break; 98 default: 99 TDB_LOG((tdb, TDB_DEBUG_ERROR, "os2_file_locks failed, lock_fd=%d flags=%x start=%d off=%d len=%d (arc=%d)\n", 100 tdb->lock_fd, flags, start, offset, len, arc)); 101 } 102 return -1; 103 } 104 105 return 0; 106 } 107 #else /* __OS2__ */ 35 108 static int fcntl_lock(struct tdb_context *tdb, 36 109 int rw, off_t off, off_t len, bool waitflag) … … 44 117 fl.l_pid = 0; 45 118 46 #ifdef __OS2__47 int rc = 0;48 int lockFile = 0;49 50 if (off == ACTIVE_LOCK || off == OPEN_LOCK || off == TRANSACTION_LOCK)51 lockFile = tdb->hActiveLock;52 else53 lockFile = tdb->fd;54 55 int cmd = 0;56 if (waitflag)57 cmd = F_SETLKW;58 else59 cmd = F_SETLK;60 61 rc = fcntl(lockFile, cmd, &fl);62 // if the first lock doesn't work and it's a complete lock,63 // we split it in 2 parts. first hash size*4 and then the rest64 if (rc != 0 && off == FREELIST_TOP && len == 0) {65 fl.l_len = tdb->header.hash_size * 4;66 rc = fcntl(lockFile, cmd, &fl);67 if (rc == 0) {68 fl.l_start = off + tdb->header.hash_size * 4;69 fl.l_len = 0;70 rc = fcntl(lockFile, cmd, &fl);71 }72 }73 74 TDB_LOG((tdb, TDB_DEBUG_TRACE,"fcntl_lock: (fd=%d) offset=%lld rw_type=%d len=%lld waitflag=%d (rc=%d) pid=%d\n",75 lockFile, off, rw, len, waitflag, rc, getpid()));76 77 return rc;78 #else79 119 if (waitflag) 80 120 return fcntl(tdb->fd, F_SETLKW, &fl); 81 121 else 82 122 return fcntl(tdb->fd, F_SETLK, &fl); 83 #endif84 123 } 85 124 … … 151 190 fl.l_pid = 0; 152 191 153 #ifdef __OS2__154 int rc = 0;155 int lockFile = 0;156 if (off == ACTIVE_LOCK || off == OPEN_LOCK || off == TRANSACTION_LOCK)157 lockFile = tdb->hActiveLock;158 else159 lockFile = tdb->fd;160 161 rc = fcntl(lockFile, F_SETLKW, &fl);162 // if the first unlock doesn't work and it's a complete unlock,163 // we split it in 2 parts. first hash size*4 and then the rest164 // as it was locked that way as well. and it seems fcntl() doesn't care165 if (rc != 0 && off == FREELIST_TOP && len == 0) {166 fl.l_len = tdb->header.hash_size * 4;167 rc = fcntl(lockFile, F_SETLKW, &fl);168 if (rc == 0) {169 fl.l_start = off + tdb->header.hash_size * 4;170 fl.l_len = 0;171 rc = fcntl(lockFile, F_SETLKW, &fl);172 }173 }174 175 TDB_LOG((tdb, TDB_DEBUG_TRACE,"fcntl_unlock: (fd=%d) offset=%lld rw_type=%d len=%lld (rc=%d) pid=%d\n",176 lockFile, off, rw, len, rc, getpid()));177 178 return rc;179 #else180 192 return fcntl(tdb->fd, F_SETLKW, &fl); 181 #endif 182 } 193 } 194 #endif /* __OS2__ */ 183 195 184 196 /* list -1 is the alloc list, otherwise a hash chain. */ … … 196 208 note that a len of zero means lock to end of file 197 209 */ 210 #ifdef __OS2__ 211 static int tdb_brlock_ex(struct tdb_context *tdb, 212 int rw_type, tdb_off_t start, 213 tdb_off_t offset, size_t len, 214 enum tdb_lock_flags flags) 215 #else 198 216 int tdb_brlock(struct tdb_context *tdb, 199 217 int rw_type, tdb_off_t offset, size_t len, 200 218 enum tdb_lock_flags flags) 219 #endif 201 220 { 202 221 int ret; … … 215 234 } 216 235 236 #ifdef __OS2__ 237 int os2_flags = OS2_FL_LOCK; 238 if (rw_type == F_WRLCK) { 239 os2_flags |= OS2_FL_RW; 240 } 241 if (flags & TDB_LOCK_WAIT) { 242 os2_flags |= OS2_FL_WAIT; 243 } 244 if (flags & TDB_LOCK_UPGRADE) { 245 os2_flags |= OS2_FL_UPGRADE; 246 } 247 #endif 248 217 249 do { 250 #ifdef __OS2__ 251 ret = os2_set_file_locks(tdb, os2_flags, start, offset, len); 252 #else 218 253 ret = fcntl_lock(tdb, rw_type, offset, len, 219 254 flags & TDB_LOCK_WAIT); 255 #endif 220 256 /* Check for a sigalarm break. */ 221 257 if (ret == -1 && errno == EINTR && … … 232 268 * locks. */ 233 269 if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) { 234 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d \n",235 tdb->fd, offset, rw_type, flags, (int)len ));270 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d (errno=%d)\n", 271 tdb->fd, offset, rw_type, flags, (int)len, errno)); 236 272 } 237 273 return -1; … … 240 276 } 241 277 278 #ifdef __OS2__ 279 int tdb_brlock(struct tdb_context *tdb, 280 int rw_type, tdb_off_t offset, size_t len, 281 enum tdb_lock_flags flags) 282 { 283 return tdb_brlock_ex(tdb, rw_type, offset, offset, len, flags); 284 } 285 #endif 286 287 #ifdef __OS2__ 288 static int tdb_brunlock_ex(struct tdb_context *tdb, 289 int rw_type, tdb_off_t start, 290 tdb_off_t offset, size_t len) 291 #else 242 292 int tdb_brunlock(struct tdb_context *tdb, 243 293 int rw_type, tdb_off_t offset, size_t len) 294 #endif 244 295 { 245 296 int ret; … … 250 301 251 302 do { 303 #ifdef __OS2__ 304 ret = os2_set_file_locks(tdb, rw_type == F_WRLCK ? OS2_FL_RW : 0, 305 start, offset, len); 306 #else 252 307 ret = fcntl_unlock(tdb, rw_type, offset, len); 308 #endif 253 309 } while (ret == -1 && errno == EINTR); 254 310 255 311 if (ret == -1) { 256 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d \n",257 tdb->fd, offset, rw_type, (int)len ));312 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d (errno=%d)\n", 313 tdb->fd, offset, rw_type, (int)len, errno)); 258 314 } 259 315 return ret; 260 316 } 317 318 #ifdef __OS2__ 319 int tdb_brunlock(struct tdb_context *tdb, 320 int rw_type, tdb_off_t offset, size_t len) 321 { 322 return tdb_brunlock_ex(tdb, rw_type, offset, offset, len); 323 } 324 #endif 261 325 262 326 /* … … 285 349 while (count--) { 286 350 struct timeval tv; 287 #ifdef __OS2__288 // we need to remove locks, as upgrade doesn't work289 tdb_brunlock(tdb, F_RDLCK, FREELIST_TOP, 0);290 #endif291 351 if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, 292 TDB_LOCK_WAIT|TDB_LOCK_PROBE ) == 0) {352 TDB_LOCK_WAIT|TDB_LOCK_PROBE|TDB_LOCK_UPGRADE) == 0) { 293 353 tdb->allrecord_lock.ltype = F_WRLCK; 294 354 tdb->allrecord_lock.off = 0; … … 580 640 } 581 641 642 #ifdef __OS2__ 643 #define TDB_ADJLOCK_START_DECL size_t start, 644 #define TDB_ADJLOCK_START start, 645 #define TDB_ADJLOCK(tdb, rw_type, start, offset, len, flags) \ 646 tdb_brlock_ex(tdb, rw_type, start, offset, len, flags) 647 #define TDB_ADJUNLOCK(tdb, rw_type, start, offset, len) \ 648 tdb_brunlock_ex(tdb, rw_type, start, offset, len) 649 #define TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, offset, len) \ 650 tdb_chainlock_gradual(tdb, ltype, flags, start, offset, len) 651 #else 652 #define TDB_ADJLOCK_START_DECL 653 #define TDB_ADJLOCK_START_REF 654 #define TDB_ADJLOCK(tdb, rw_type, start, offset, len, flags) \ 655 tdb_brlock(tdb, rw_type, offset, len, flags) 656 #define TDB_ADJUNLOCK(tdb, rw_type, start, offset, len) \ 657 tdb_brunlock(tdb, rw_type, offset, len) 658 #define TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, offset, len) \ 659 tdb_chainlock_gradual(tdb, ltype, flags, offset, len) 660 #endif 661 582 662 /* We only need to lock individual bytes, but Linux merges consecutive locks 583 663 * so we lock in contiguous ranges. */ 584 664 static int tdb_chainlock_gradual(struct tdb_context *tdb, 585 665 int ltype, enum tdb_lock_flags flags, 586 size_t off, size_t len)666 TDB_ADJLOCK_START_DECL size_t off, size_t len) 587 667 { 588 668 int ret; … … 591 671 if (len <= 4) { 592 672 /* Single record. Just do blocking lock. */ 593 return tdb_brlock(tdb, ltype, off, len, flags);673 return TDB_ADJLOCK(tdb, ltype, start, off, len, flags); 594 674 } 595 675 596 676 /* First we try non-blocking. */ 597 ret = tdb_brlock(tdb, ltype, off, len, nb_flags);677 ret = TDB_ADJLOCK(tdb, ltype, start, off, len, nb_flags); 598 678 if (ret == 0) { 599 679 return 0; … … 601 681 602 682 /* Try locking first half, then second. */ 603 ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2);683 ret = TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, off, len / 2); 604 684 if (ret == -1) 605 685 return -1; 606 686 607 ret = tdb_chainlock_gradual(tdb, ltype, flags,687 ret = TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, 608 688 off + len / 2, len - len / 2); 609 689 if (ret == -1) { 610 tdb_brunlock(tdb, ltype, off, len / 2);690 TDB_ADJUNLOCK(tdb, ltype, start, off, len / 2); 611 691 return -1; 612 692 } … … 634 714 * It is (1) which cause the starvation problem, so we're only 635 715 * gradual for that. */ 636 if ( tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP,716 if (TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, FREELIST_TOP, FREELIST_TOP, 637 717 tdb->header.hash_size * 4) == -1) { 638 718 return -1; … … 640 720 641 721 /* Grab individual record locks. */ 642 if ( tdb_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0,643 722 if (TDB_ADJLOCK(tdb, ltype, FREELIST_TOP, lock_offset(tdb->header.hash_size), 0, 723 flags) == -1) { 644 724 tdb_brunlock(tdb, ltype, FREELIST_TOP, 645 725 tdb->header.hash_size * 4);
Note:
See TracChangeset
for help on using the changeset viewer.