def PrepareWriteDir(self, arg, mode='normal', post_entry=None): if not arg.map_dir(): return False if arg.needlock: Util.FLock(arg.fd) if post_entry: (newpost, newid) = self.FindPost(arg.ent, post_entry.id, mode) if newpost is None: Util.FUnlock(arg.fd) return False arg.ent = newid return True
def index_board(self, board): """ Index one board (name: board)""" boardobj = BoardManager.BoardManager.GetBoard(board) if not boardobj: Log.error("Error loading board %s" % board) return if board in self.board_info: idx_obj = self.board_info[board] else: idx_obj = IndexBoardInfo(board, 0) self.board_info[board] = idx_obj bdir_path = boardobj.GetDirPath() with open(bdir_path, 'rb') as bdir: Util.FLock(bdir, shared=True) try: if not board in self.state.locks: self.state.locks[board] = threading.Lock() status = os.stat(bdir_path) if status.st_mtime <= idx_obj.last_idx: # why <? anyway... return Log.debug("Board %s updated. Indexing..." % board) # index into buffer table self.init_buf(board) for idx in xrange(status.st_size / PostEntry.PostEntry.size): post_entry = PostEntry.PostEntry( bdir.read(PostEntry.PostEntry.size)) self.insert_entry(board, post_entry, idx) self.conn.commit() # commit buffer table self.state.locks[board].acquire() try: self.remove_idx_status(idx_obj) self.commit_buf(board) self.create_db_index(board) idx_obj.last_idx = status.st_mtime self.insert_idx_status(idx_obj) finally: self.state.locks[board].release() Log.debug("Board %s indexed." % board) finally: Util.FUnlock(bdir)
def DelPost(self, user, post_id, post_xid, mode='normal'): # from del_post() if post_id > self.PostCount(mode): raise WrongArgs("out of range") if self.name == "syssecurity" or self.name == "junk" or self.name == "deleted": raise WrongArgs("invalid board: %s" % self.name) if mode == "junk" or mode == "deleted": raise WrongArgs("invalid mode: %s" % mode) (post_entry, new_post_id) = self.FindPost(post_id, post_xid, mode) if post_entry is None: raise NotFound("post not found") if not post_entry.CanBeDeleted(user, self): raise NoPerm("permission denied") owned = user.IsOwner(post_entry) arg = WriteDirArg() arg.filename = self.GetDirPath(mode) if mode == 'normal' or mode == 'digest': arg.ent = new_post_id # from do_del_post() succ = self.PrepareWriteDir(arg, mode, post_entry) if not succ: raise ServerError("fail to prepare directory write") self.DeleteEntry(arg.fileptr, arg.ent, arg.size, arg.fd) Util.FUnlock(arg.fd) self.SetUpdate('title', True) self.CancelPost(user, post_entry, owned, True) self.UpdateLastPost() if post_entry.IsMarked(): self.SetUpdate('mark', True) if (mode == 'normal' and not (post_entry.IsMarked() and post_entry.CannotReply() and post_entry.IsForwarded()) and not self.IsJunkBoard()): if owned: user.DecNumPosts() elif "." not in post_entry.owner and Config.BMDEL_DECREASE: user = UserManager.UserManager.LoadUser(post_entry.owner) if user is not None and not self.IsSysmailBoard(): user.DecNumPosts() arg.free()
def EditPost(self, session, post_xid, post_id=0, new_title=None, content=None, mode='normal', attach_to_remove=set(), add_attach_list=[]): (post_entry, post_id) = self.FindPost(post_id, post_xid, mode) if post_entry is None: raise NotFound("post not found") if (self.name == "syssecurity" or self.name == "junk" or self.name == "deleted"): raise WrongArgs("can't edit post in board %s" % self.name) if mode == "junk" or mode == "deleted": raise WrongArgs("can't edit post in mode %s" % mode) if self.CheckReadonly(): raise WrongArgs("board %s is read-only" % self.name) user = session.GetUser() if not post_entry.CanBeEdit(user, self): raise NoPerm("you can't edit this post") if self.DeniedUser(user): raise NoPerm("you can't edit on board %s" % self.name) post_path = self.GetBoardPath(post_entry.filename) post = Post(post_path, post_entry) if content is None: content = post.GetBody() first_attach_pos = 0 need_update = False new_post_path = post_path + ".new" if new_title is not None and new_title != Util.gbkDec( post_entry.title): post_entry.title = Util.gbkEnc(new_title) need_update = True with open(post_path, "r+b") as postf: Util.FLock(postf) try: attach_list = post.GetAttachList() newpost = Post(new_post_path, post_entry) newpost.open() try: newpost.EditHeaderFrom(post, new_title) size_header = newpost.pos() newpost.EditContent(content, session, post) content_len = newpost.pos() - size_header if content_len != post_entry.eff_size: post_entry.eff_size = content_len need_update = True # copy original attachments orig_attach_id = 0 for attach_entry in attach_list: if not orig_attach_id in attach_to_remove: try: attach_pos = newpost.AppendAttachFrom( post, attach_entry) if first_attach_pos == 0: first_attach_pos = attach_pos except: pass orig_attach_id += 1 # add new attachments for attach_entry in add_attach_list: filename = attach_entry['name'] tmpfile = attach_entry['store_id'] if (not store.Store.verify_id(tmpfile)): continue tmpfile = store.Store.path_from_id(tmpfile) try: attach_pos = newpost.AddAttachSelf( filename, tmpfile) if first_attach_pos == 0: first_attach_pos = attach_pos except Exception as e: Log.warn("fail to add attach: %r" % e) finally: newpost.close() os.rename(new_post_path, post_path) finally: try: os.remove(new_post_path) except: pass Util.FUnlock(postf) if first_attach_pos != post_entry.attachment: post_entry.attachment = first_attach_pos need_update = True if need_update: # fail to update post info is not that important if not self.UpdatePostEntry(post_entry, post_id, mode): Log.warn("fail to update post entry!")
def Unlock(lockf): #SemLock.Unlock(Config.UCACHE_SEMLOCK) # Log.debug("Utmp.Unlock") Util.FUnlock(lockf) os.close(lockf)