robust_mutex_lock_file() { permissions p; p.set_unrestricted(); //Remove old lock files of other processes remove_old_robust_lock_files(); //Create path and obtain lock file path for this process create_and_get_robust_lock_file_path(fname, get_current_process_id()); //Now try to open or create the lock file fd = create_or_open_file(fname.c_str(), read_write, p); //If we can't open or create it, then something unrecoverable has happened if(fd == invalid_file()){ throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file"); } //Now we must take in care a race condition with another process //calling "remove_old_robust_lock_files()". No other threads from this //process will be creating the lock file because intermodule_singleton //guarantees this. So let's loop acquiring the lock and checking if we //can't exclusively create the file (if the file is erased by another process //then this exclusive open would fail). If the file can't be exclusively created //then we have correctly open/create and lock the file. If the file can //be exclusively created, then close previous locked file and try again. while(1){ bool acquired; if(!try_acquire_file_lock(fd, acquired) || !acquired ){ throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock"); } //Creating exclusively must fail with already_exists_error //to make sure we've locked the file and no one has //deleted it between creation and locking file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p); if(fd2 != invalid_file()){ close_file(fd); fd = fd2; continue; } //If exclusive creation fails with expected error go ahead else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist //Leak descriptor to mantain the file locked until the process dies break; } //If exclusive creation fails with unexpected error throw an unrecoverable error else{ close_file(fd); throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error"); } } }
inline int open_or_create_and_lock_file(const char *name) { permissions p; p.set_unrestricted(); while(1){ int fd = create_or_open_file(name, read_write, p); if(fd < 0){ return fd; } if(!try_lock_locking_file(fd)){ close(fd); return -1; } struct stat s; if(0 == stat(name, &s)){ return fd; } else{ close(fd); } } }
inline bool file_wrapper::priv_open_or_create (detail::create_enum_t type, const char *filename, mode_t mode) { m_filename = filename; if(mode != read_only && mode != read_write){ error_info err(mode_error); throw interprocess_exception(err); } //Open file existing native API to obtain the handle switch(type){ case detail::DoOpen: m_handle = open_existing_file(filename, mode); break; case detail::DoCreate: m_handle = create_new_file(filename, mode); break; case detail::DoOpenOrCreate: m_handle = create_or_open_file(filename, mode); break; default: { error_info err = other_error; throw interprocess_exception(err); } } //Check for error if(m_handle == invalid_file()){ throw interprocess_exception(error_info(system_error_code())); } m_mode = mode; return true; }
inline int open_or_create_and_lock_file(const char *name) { permissions p; p.set_unrestricted(); while(1){ file_handle_t handle = create_or_open_file(name, read_write, p); int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); if(fd < 0){ close_file(handle); return fd; } if(!try_lock_locking_file(fd)){ _close(fd); return -1; } struct _stat s; if(0 == _stat(name, &s)){ return fd; } else{ _close(fd); } } }
bool output_sgf (const char *filename) { int current = -1; union prop_data_t temp_data; int saved = current_node; sgf_fd = create_or_open_file (filename); if (sgf_fd < 0) { return false; } DEBUGF ("outputting to: %s (%d)\n", filename, sgf_fd); empty_stack (&parse_stack); rb->lseek (sgf_fd, 0, SEEK_SET); rb->ftruncate (sgf_fd, 0); if (sgf_fd < 0) { return false; } if (tree_head < 0) { close_file (&sgf_fd); return false; } push_int_stack (&parse_stack, tree_head); while (pop_int_stack (&parse_stack, ¤t)) { int var_to_process = 0; int temp_prop = get_prop_sgf (current, PROP_VARIATION_TO_PROCESS, NULL); if (temp_prop >= 0) { var_to_process = get_prop (temp_prop)->data.number; } current_node = current; if (var_to_process > 0) { write_char (sgf_fd, ')'); } if (var_to_process == stupid_num_variations ()) { delete_prop_sgf (current, PROP_VARIATION_TO_PROCESS); continue; } else { write_char (sgf_fd, '\n'); write_char (sgf_fd, '('); /* we need to do more processing on this branchpoint, either to do more variations or to output the ')' */ push_int_stack (&parse_stack, current); /* increment the stored variation to process */ temp_data.number = var_to_process + 1; add_or_set_prop_sgf (current, PROP_VARIATION_TO_PROCESS, temp_data); } rb->yield (); /* now we did the setup for sibling varaitions to be processed so do the actual outputting of a game tree branch */ go_to_variation_sgf (var_to_process); output_gametree (); } current_node = saved; close_file (&sgf_fd); DEBUGF ("done outputting, file closed\n"); return true; }