예제 #1
0
int
alock_close ( alock_info_t * info, int nosave )
{
	alock_slot_t slot_data;
	int res;

	if ( !info->al_slot )
		return ALOCK_CLEAN;

	(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));

	res = alock_grab_lock (info->al_fd, 0);
	if (res == -1) {
fail:
		/* Windows doesn't clean up locks immediately when a process exits.
		 * Make sure we release our locks, to prevent stale locks from
		 * hanging around.
		 */
		alock_release_lock (info->al_fd, 0);
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	/* mark our slot as clean */
	res = alock_read_slot (info, &slot_data);
	if (res == -1) {
		if (slot_data.al_appname != NULL) 
			ber_memfree (slot_data.al_appname);
		goto fail;
	}
	slot_data.al_lock = ALOCK_UNLOCKED;
	if ( nosave )
		slot_data.al_lock |= ALOCK_NOSAVE;
	/* since we have slot 0 locked, we don't need our slot lock */
	res = alock_release_lock (info->al_fd, info->al_slot);
	if (res == -1) {
		goto fail;
	}
	res = alock_write_slot (info, &slot_data);
	if (res == -1) {
		if (slot_data.al_appname != NULL) 
			ber_memfree (slot_data.al_appname);
		goto fail;
	}
	if (slot_data.al_appname != NULL) {
		ber_memfree (slot_data.al_appname);
		slot_data.al_appname = NULL;
	}

	res = alock_release_lock (info->al_fd, 0);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	res = close (info->al_fd);
	if (res == -1) return ALOCK_UNSTABLE;
	
	return ALOCK_CLEAN;
}
예제 #2
0
int
alock_close ( alock_info_t * info, int nosave )
{
	alock_slot_t slot_data;
	int res;

	if ( !info->al_slot )
		return ALOCK_CLEAN;

	(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));

	res = alock_grab_lock (info->al_fd, 0);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	/* mark our slot as clean */
	res = alock_read_slot (info, &slot_data);
	if (res == -1) {
		close (info->al_fd);
		if (slot_data.al_appname != NULL) 
			ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}
	slot_data.al_lock = ALOCK_UNLOCKED;
	if ( nosave )
		slot_data.al_lock |= ALOCK_NOSAVE;
	res = alock_write_slot (info, &slot_data);
	if (res == -1) {
		close (info->al_fd);
		if (slot_data.al_appname != NULL) 
			ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}
	if (slot_data.al_appname != NULL) {
		ber_memfree (slot_data.al_appname);
		slot_data.al_appname = NULL;
	}

	res = alock_release_lock (info->al_fd, info->al_slot);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}
	res = alock_release_lock (info->al_fd, 0);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	res = close (info->al_fd);
	if (res == -1) return ALOCK_UNSTABLE;
	
	return ALOCK_CLEAN;
}
예제 #3
0
int 
alock_recover ( alock_info_t * info )
{
	struct stat statbuf;
	alock_slot_t slot_data;
	alock_info_t scan_info;
	int res, max_slot;

	assert (info != NULL);

	scan_info.al_fd = info->al_fd;

	(void) memset ((void *) &slot_data, 0, sizeof(alock_slot_t));

	res = alock_grab_lock (info->al_fd, 0);
	if (res == -1) {
		goto fail;
	}

	res = fstat (info->al_fd, &statbuf);
	if (res == -1) {
		goto fail;
	}

	max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
	for (scan_info.al_slot = 1; 
	     scan_info.al_slot < max_slot;
	     ++ scan_info.al_slot) {
		if (scan_info.al_slot != info->al_slot) {
			res = alock_query_slot (&scan_info) & ~ALOCK_NOSAVE;

			if (res == ALOCK_LOCKED
			    || res == ALOCK_UNIQUE) {
				/* recovery attempt on an active db? */
				goto fail;
				
			} else if (res == ALOCK_DIRTY) {
				/* mark it clean */
				res = alock_read_slot (&scan_info, &slot_data);
				if (res == -1) {
					goto fail;
				}
				slot_data.al_lock = ALOCK_UNLOCKED;
				res = alock_write_slot (&scan_info, &slot_data);
				if (res == -1) {
					if (slot_data.al_appname != NULL) 
						ber_memfree (slot_data.al_appname);
					goto fail;
				}
				if (slot_data.al_appname != NULL) {
					ber_memfree (slot_data.al_appname);
					slot_data.al_appname = NULL;
				}
				
			} else if (res == -1) {
				goto fail;

			}
		}
	}

	res = alock_release_lock (info->al_fd, 0);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	return ALOCK_CLEAN;

fail:
	alock_release_lock (info->al_fd, 0);
	close (info->al_fd);
	return ALOCK_UNSTABLE;
}
예제 #4
0
int 
alock_scan ( alock_info_t * info )
{
	struct stat statbuf;
	alock_info_t scan_info;
	int res, max_slot;
	int dirty_count, live_count, nosave;

	assert (info != NULL);

	scan_info.al_fd = info->al_fd;

	res = alock_grab_lock (info->al_fd, 0);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	res = fstat (info->al_fd, &statbuf);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
	dirty_count = 0;
	live_count = 0;
	nosave = 0;
	for (scan_info.al_slot = 1; 
	     scan_info.al_slot < max_slot;
	     ++ scan_info.al_slot) {
		if (scan_info.al_slot != info->al_slot) {
			res = alock_query_slot (&scan_info);

			if (res & ALOCK_NOSAVE) {
				nosave = ALOCK_NOSAVE;
				res ^= ALOCK_NOSAVE;
			}

			if (res == ALOCK_LOCKED) {
				++live_count;
				
			} else if (res == ALOCK_DIRTY) {
				++dirty_count;

			} else if (res == -1) {
				close (info->al_fd);
				return ALOCK_UNSTABLE;

			}
		}
	}

	res = alock_release_lock (info->al_fd, 0);
	if (res == -1) {
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}

	if (dirty_count) {
		if (live_count) {
			close (info->al_fd);
			return ALOCK_UNSTABLE;
		} else {
			return ALOCK_RECOVER | nosave;
		}
	}
	
	return ALOCK_CLEAN | nosave;
}
예제 #5
0
int 
alock_open ( alock_info_t * info,
	     const char * appname,
	     const char * envdir,
	     int locktype )
{
	struct stat statbuf;
	alock_info_t scan_info;
	alock_slot_t slot_data;
	char * filename;
	int res, max_slot;
	int dirty_count, live_count, nosave;
	char *ptr;

	assert (info != NULL);
	assert (appname != NULL);
	assert (envdir != NULL);
	assert ((locktype & ALOCK_SMASK) >= 1 && (locktype & ALOCK_SMASK) <= 2);

	slot_data.al_lock = locktype;
	slot_data.al_stamp = time(NULL);
	slot_data.al_pid = getpid();
	slot_data.al_appname = ber_memcalloc (1, ALOCK_MAX_APPNAME);
	if (slot_data.al_appname == NULL) {
		return ALOCK_UNSTABLE;
	}
	strncpy (slot_data.al_appname, appname, ALOCK_MAX_APPNAME-1);
	slot_data.al_appname [ALOCK_MAX_APPNAME-1] = '\0';

	filename = ber_memcalloc (1, strlen (envdir) + strlen ("/alock") + 1);
	if (filename == NULL ) {
		ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}
	ptr = lutil_strcopy(filename, envdir);
	lutil_strcopy(ptr, "/alock");
#ifdef _WIN32
	{ HANDLE handle = CreateFile (filename, GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL);
		info->al_fd = _open_osfhandle (handle, 0);
	}
#else
	info->al_fd = open (filename, O_CREAT|O_RDWR, 0666);
#endif
	ber_memfree (filename);
	if (info->al_fd < 0) {
		ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}
	info->al_slot = 0;

	res = alock_grab_lock (info->al_fd, 0);
	if (res == -1) { 
		close (info->al_fd);
		ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}

	res = fstat (info->al_fd, &statbuf);
	if (res == -1) { 
		close (info->al_fd);
		ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}

	max_slot = (statbuf.st_size + ALOCK_SLOT_SIZE - 1) / ALOCK_SLOT_SIZE;
	dirty_count = 0;
	live_count = 0;
	nosave = 0;
	scan_info.al_fd = info->al_fd;
	for (scan_info.al_slot = 1; 
	     scan_info.al_slot < max_slot;
	     ++ scan_info.al_slot) {
		if (scan_info.al_slot != info->al_slot) {
			res = alock_query_slot (&scan_info);

			if (res & ALOCK_NOSAVE) {
				nosave = ALOCK_NOSAVE;
				res ^= ALOCK_NOSAVE;
			}
			if (res == ALOCK_UNLOCKED
			    && info->al_slot == 0) {
				info->al_slot = scan_info.al_slot;

			} else if (res == ALOCK_LOCKED) {
				++live_count;

			} else if (res == ALOCK_UNIQUE
				&& (( locktype & ALOCK_SMASK ) == ALOCK_UNIQUE
				|| nosave )) {
				close (info->al_fd);
				ber_memfree (slot_data.al_appname);
				return ALOCK_BUSY;

			} else if (res == ALOCK_DIRTY) {
				++dirty_count;

			} else if (res == -1) {
				close (info->al_fd);
				ber_memfree (slot_data.al_appname);
				return ALOCK_UNSTABLE;

			}
		}
	}

	if (dirty_count && live_count) {
		close (info->al_fd);
		ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}
	
	if (info->al_slot == 0) info->al_slot = max_slot + 1;
	res = alock_grab_lock (info->al_fd,
			       info->al_slot);
	if (res == -1) { 
		close (info->al_fd);
		ber_memfree (slot_data.al_appname);
		return ALOCK_UNSTABLE;
	}
	res = alock_write_slot (info, &slot_data);
	ber_memfree (slot_data.al_appname);
	if (res == -1) { 
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}
	alock_share_lock (info->al_fd, info->al_slot);

	res = alock_release_lock (info->al_fd, 0);
	if (res == -1) { 
		close (info->al_fd);
		return ALOCK_UNSTABLE;
	}
	
	if (dirty_count) return ALOCK_RECOVER | nosave;
	return ALOCK_CLEAN | nosave;
}