示例#1
0
文件: Lock.c 项目: carriercomm/lucy
bool
LFLock_Maybe_Delete_File_IMP(LockFileLock *self, String *path,
                             bool delete_mine, bool delete_other) {
    LockFileLockIVARS *const ivars = LFLock_IVARS(self);
    Folder *folder  = ivars->folder;
    bool    success = false;

    // Only delete locks that start with our lock name.
    if (!Str_Starts_With_Utf8(path, "locks", 5)) {
        return false;
    }
    StringIterator *iter = Str_Top(path);
    StrIter_Advance(iter, 5 + 1);
    if (!StrIter_Starts_With(iter, ivars->name)) {
        DECREF(iter);
        return false;
    }
    DECREF(iter);

    // Attempt to delete dead lock file.
    if (Folder_Exists(folder, path)) {
        Hash *hash = (Hash*)Json_slurp_json(folder, path);
        if (hash != NULL && Obj_Is_A((Obj*)hash, HASH)) {
            String *pid_buf = (String*)Hash_Fetch_Utf8(hash, "pid", 3);
            String *host    = (String*)Hash_Fetch_Utf8(hash, "host", 4);
            String *name    = (String*)Hash_Fetch_Utf8(hash, "name", 4);

            // Match hostname and lock name.
            if (host != NULL
                && Str_Is_A(host, STRING)
                && Str_Equals(host, (Obj*)ivars->host)
                && name != NULL
                && Str_Is_A(name, STRING)
                && Str_Equals(name, (Obj*)ivars->name)
                && pid_buf != NULL
                && Str_Is_A(pid_buf, STRING)
               ) {
                // Verify that pid is either mine or dead.
                int pid = (int)Str_To_I64(pid_buf);
                if ((delete_mine && pid == PID_getpid())  // This process.
                    || (delete_other && !PID_active(pid)) // Dead pid.
                   ) {
                    if (Folder_Delete(folder, path)) {
                        success = true;
                    }
                    else {
                        String *mess
                            = MAKE_MESS("Can't delete '%o'", path);
                        DECREF(hash);
                        Err_throw_mess(ERR, mess);
                    }
                }
            }
        }
        DECREF(hash);
    }

    return success;
}
示例#2
0
文件: Lock.c 项目: pavansondur/lucy
LockFileLock*
LFLock_init(LockFileLock *self, Folder *folder, const CharBuf *name,
            const CharBuf *host, int32_t timeout, int32_t interval) {
    int pid = PID_getpid();
    Lock_init((Lock*)self, folder, name, host, timeout, interval);
    self->link_path = CB_newf("%o.%o.%i64", self->lock_path, host, pid);
    return self;
}
示例#3
0
文件: Lock.c 项目: carriercomm/lucy
LockFileLock*
LFLock_init(LockFileLock *self, Folder *folder, String *name,
            String *host, int32_t timeout, int32_t interval) {
    int pid = PID_getpid();
    Lock_init((Lock*)self, folder, name, host, timeout, interval);
    LockFileLockIVARS *const ivars = LFLock_IVARS(self);
    ivars->link_path = Str_newf("%o.%o.%i64", ivars->lock_path, host, pid);
    return self;
}
示例#4
0
文件: Lock.c 项目: pavansondur/lucy
bool_t
LFLock_maybe_delete_file(LockFileLock *self, const CharBuf *path,
                         bool_t delete_mine, bool_t delete_other) {
    Folder *folder  = self->folder;
    bool_t  success = false;
    ZombieCharBuf *scratch = ZCB_WRAP(path);

    // Only delete locks that start with our lock name.
    CharBuf *lock_dir_name = (CharBuf*)ZCB_WRAP_STR("locks", 5);
    if (!ZCB_Starts_With(scratch, lock_dir_name)) {
        return false;
    }
    ZCB_Nip(scratch, CB_Get_Size(lock_dir_name) + 1);
    if (!ZCB_Starts_With(scratch, self->name)) {
        return false;
    }

    // Attempt to delete dead lock file.
    if (Folder_Exists(folder, path)) {
        Hash *hash = (Hash*)Json_slurp_json(folder, path);
        if (hash != NULL && Obj_Is_A((Obj*)hash, HASH)) {
            CharBuf *pid_buf = (CharBuf*)Hash_Fetch_Str(hash, "pid", 3);
            CharBuf *host    = (CharBuf*)Hash_Fetch_Str(hash, "host", 4);
            CharBuf *name
                = (CharBuf*)Hash_Fetch_Str(hash, "name", 4);

            // Match hostname and lock name.
            if (host != NULL
                && CB_Equals(host, (Obj*)self->host)
                && name != NULL
                && CB_Equals(name, (Obj*)self->name)
                && pid_buf != NULL
               ) {
                // Verify that pid is either mine or dead.
                int pid = (int)CB_To_I64(pid_buf);
                if ((delete_mine && pid == PID_getpid())  // This process.
                    || (delete_other && !PID_active(pid)) // Dead pid.
                   ) {
                    if (Folder_Delete(folder, path)) {
                        success = true;
                    }
                    else {
                        CharBuf *mess
                            = MAKE_MESS("Can't delete '%o'", path);
                        DECREF(hash);
                        Err_throw_mess(ERR, mess);
                    }
                }
            }
        }
        DECREF(hash);
    }

    return success;
}
示例#5
0
文件: Lock.c 项目: pavansondur/lucy
bool_t
LFLock_request(LockFileLock *self) {
    Hash   *file_data;
    bool_t wrote_json;
    bool_t success = false;
    bool_t deletion_failed = false;

    if (Folder_Exists(self->folder, self->lock_path)) {
        Err_set_error((Err*)LockErr_new(CB_newf("Can't obtain lock: '%o' exists",
                                                self->lock_path)));
        return false;
    }

    // Create the "locks" subdirectory if necessary.
    CharBuf *lock_dir_name = (CharBuf*)ZCB_WRAP_STR("locks", 5);
    if (!Folder_Exists(self->folder, lock_dir_name)) {
        if (!Folder_MkDir(self->folder, lock_dir_name)) {
            Err *mkdir_err = (Err*)CERTIFY(Err_get_error(), ERR);
            LockErr *err = LockErr_new(CB_newf("Can't create 'locks' directory: %o",
                                               Err_Get_Mess(mkdir_err)));
            // Maybe our attempt failed because another process succeeded.
            if (Folder_Find_Folder(self->folder, lock_dir_name)) {
                DECREF(err);
            }
            else {
                // Nope, everything failed, so bail out.
                Err_set_error((Err*)err);
                return false;
            }
        }
    }

    // Prepare to write pid, lock name, and host to the lock file as JSON.
    file_data = Hash_new(3);
    Hash_Store_Str(file_data, "pid", 3,
                   (Obj*)CB_newf("%i32", (int32_t)PID_getpid()));
    Hash_Store_Str(file_data, "host", 4, INCREF(self->host));
    Hash_Store_Str(file_data, "name", 4, INCREF(self->name));

    // Write to a temporary file, then use the creation of a hard link to
    // ensure atomic but non-destructive creation of the lockfile with its
    // complete contents.
    wrote_json = Json_spew_json((Obj*)file_data, self->folder, self->link_path);
    if (wrote_json) {
        success = Folder_Hard_Link(self->folder, self->link_path,
                                   self->lock_path);
        if (!success) {
            Err *hard_link_err = (Err*)CERTIFY(Err_get_error(), ERR);
            Err_set_error((Err*)LockErr_new(CB_newf("Failed to obtain lock at '%o': %o",
                                                    self->lock_path,
                                                    Err_Get_Mess(hard_link_err))));
        }
        deletion_failed = !Folder_Delete(self->folder, self->link_path);
    }
    else {
        Err *spew_json_err = (Err*)CERTIFY(Err_get_error(), ERR);
        Err_set_error((Err*)LockErr_new(CB_newf("Failed to obtain lock at '%o': %o",
                                                self->lock_path,
                                                Err_Get_Mess(spew_json_err))));
    }
    DECREF(file_data);

    // Verify that our temporary file got zapped.
    if (wrote_json && deletion_failed) {
        CharBuf *mess = MAKE_MESS("Failed to delete '%o'", self->link_path);
        Err_throw_mess(ERR, mess);
    }

    return success;
}
示例#6
0
文件: Lock.c 项目: carriercomm/lucy
bool
LFLock_Request_IMP(LockFileLock *self) {
    LockFileLockIVARS *const ivars = LFLock_IVARS(self);
    bool success = false;

    if (Folder_Exists(ivars->folder, ivars->lock_path)) {
        Err_set_error((Err*)LockErr_new(Str_newf("Can't obtain lock: '%o' exists",
                                                 ivars->lock_path)));
        return false;
    }

    // Create the "locks" subdirectory if necessary.
    String *lock_dir_name = (String*)SSTR_WRAP_UTF8("locks", 5);
    if (!Folder_Exists(ivars->folder, lock_dir_name)) {
        if (!Folder_MkDir(ivars->folder, lock_dir_name)) {
            Err *mkdir_err = (Err*)CERTIFY(Err_get_error(), ERR);
            LockErr *err = LockErr_new(Str_newf("Can't create 'locks' directory: %o",
                                                Err_Get_Mess(mkdir_err)));
            // Maybe our attempt failed because another process succeeded.
            if (Folder_Find_Folder(ivars->folder, lock_dir_name)) {
                DECREF(err);
            }
            else {
                // Nope, everything failed, so bail out.
                Err_set_error((Err*)err);
                return false;
            }
        }
    }

    // Prepare to write pid, lock name, and host to the lock file as JSON.
    Hash *file_data = Hash_new(3);
    Hash_Store_Utf8(file_data, "pid", 3,
                    (Obj*)Str_newf("%i32", (int32_t)PID_getpid()));
    Hash_Store_Utf8(file_data, "host", 4, INCREF(ivars->host));
    Hash_Store_Utf8(file_data, "name", 4, INCREF(ivars->name));
    String *json = Json_to_json((Obj*)file_data);
    DECREF(file_data);

    // Write to a temporary file, then use the creation of a hard link to
    // ensure atomic but non-destructive creation of the lockfile with its
    // complete contents.

    OutStream *outstream = Folder_Open_Out(ivars->folder, ivars->link_path);
    if (!outstream) {
        ERR_ADD_FRAME(Err_get_error());
        DECREF(json);
        return false;
    }

    struct lockfile_context context;
    context.outstream = outstream;
    context.json = json;
    Err *json_error = Err_trap(S_write_lockfile_json, &context);
    bool wrote_json = !json_error;
    DECREF(outstream);
    DECREF(json);
    if (wrote_json) {
        success = Folder_Hard_Link(ivars->folder, ivars->link_path,
                                   ivars->lock_path);
        if (!success) {
            Err *hard_link_err = (Err*)CERTIFY(Err_get_error(), ERR);
            Err_set_error((Err*)LockErr_new(Str_newf("Failed to obtain lock at '%o': %o",
                                                     ivars->lock_path,
                                                     Err_Get_Mess(hard_link_err))));
        }
    }
    else {
        Err_set_error((Err*)LockErr_new(Str_newf("Failed to obtain lock at '%o': %o",
                                                 ivars->lock_path,
                                                 Err_Get_Mess(json_error))));
        DECREF(json_error);
    }

    // Verify that our temporary file got zapped.
    bool deletion_failed = !Folder_Delete(ivars->folder, ivars->link_path);
    if (deletion_failed) {
        String *mess = MAKE_MESS("Failed to delete '%o'", ivars->link_path);
        Err_throw_mess(ERR, mess);
    }

    return success;
}