blob: a49925d1628eb2597553170bc0ee9ee682fe596b [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define C_LUCY_LOCK
#include "Lucy/Util/ToolSet.h"
#include <ctype.h>
#include "Lucy/Store/Lock.h"
#include "Lucy/Store/Folder.h"
#include "Lucy/Util/Sleep.h"
Lock*
Lock_init(Lock *self, Folder *folder, String *name, int32_t timeout,
int32_t interval) {
LockIVARS *const ivars = Lock_IVARS(self);
// Validate.
if (interval <= 0) {
DECREF(self);
THROW(ERR, "Invalid value for 'interval': %i32", interval);
}
StringIterator *iter = Str_Top(name);
int32_t code_point;
while (STR_OOB != (code_point = StrIter_Next(iter))) {
if (isalnum(code_point)
|| code_point == '.'
|| code_point == '-'
|| code_point == '_'
) {
continue;
}
DECREF(self);
THROW(ERR, "Lock name contains disallowed characters: '%o'", name);
}
DECREF(iter);
// Assign.
ivars->folder = (Folder*)INCREF(folder);
ivars->timeout = timeout;
ivars->name = Str_Clone(name);
ivars->interval = interval;
return self;
}
void
Lock_Destroy_IMP(Lock *self) {
LockIVARS *const ivars = Lock_IVARS(self);
DECREF(ivars->folder);
DECREF(ivars->name);
SUPER_DESTROY(self, LOCK);
}
bool
Lock_make_lock_dir(Folder *folder) {
String *lock_dir_name = SSTR_WRAP_C("locks");
if (!Folder_MkDir(folder, lock_dir_name)) {
Err *err = (Err*)INCREF(Err_get_error());
// Maybe our attempt failed because another process succeeded.
if (Folder_Find_Folder(folder, lock_dir_name)) {
DECREF(err);
}
else {
// Nope, everything failed, so bail out.
Err_set_error(err);
return false;
}
}
return true;
}
bool
Lock_Obtain_Shared_IMP(Lock *self) {
LockIVARS *const ivars = Lock_IVARS(self);
int32_t time_left = ivars->interval == 0 ? 0 : ivars->timeout;
bool locked = Lock_Request_Shared(self);
while (!locked) {
time_left -= ivars->interval;
if (time_left <= 0) { break; }
Sleep_millisleep((uint32_t)ivars->interval);
locked = Lock_Request_Shared(self);
}
if (!locked) { ERR_ADD_FRAME(Err_get_error()); }
return locked;
}
bool
Lock_Obtain_Exclusive_IMP(Lock *self) {
LockIVARS *const ivars = Lock_IVARS(self);
int32_t time_left = ivars->interval == 0 ? 0 : ivars->timeout;
bool locked = Lock_Request_Exclusive(self);
while (!locked) {
time_left -= ivars->interval;
if (time_left <= 0) { break; }
Sleep_millisleep((uint32_t)ivars->interval);
locked = Lock_Request_Exclusive(self);
}
if (!locked) { ERR_ADD_FRAME(Err_get_error()); }
return locked;
}
/***************************************************************************/
LockErr*
LockErr_new(String *message) {
LockErr *self = (LockErr*)Class_Make_Obj(LOCKERR);
return LockErr_init(self, message);
}
LockErr*
LockErr_init(LockErr *self, String *message) {
Err_init((Err*)self, message);
return self;
}