Re: [PATCH] Editor locking update
- From: Adam Byrtek / alpha <alpha informatica agh edu pl>
- To: mc-devel gnome org
- Subject: Re: [PATCH] Editor locking update
- Date: Fri, 26 Mar 2004 18:14:08 +0100
On Thu, Mar 25, 2004 at 11:10:39PM +0100, Adam Byrtek / alpha wrote:
> Hi. I'm attaching a patch to the editor locking scheme. First of all
I'm attaching a patch which you might consider an update to the
previous one. Initially I wanted to separate them into two different
patches, but they depend heavily on each other, so I joined them
together.
This update implements mtime check to discover if the file was
modified by some other process during the current editor session (it
is a problem that locking didn't solve).
You might want to consult mailing list archives, especially:
http://mail.gnome.org/archives/mc-devel/2004-February/msg00001.html
I have also posted this patch to the Savannah PTS.
Regards
Adam
PS. I don't know if Cooledit author reads this list, but he might
consider using this patch in his own project.
--
__ _
/ _` | Adam Byrtek -*- jid alpha.jabber.lfa.pl -*- pgp 0xB25952C0
\__,_| "Każdy ideał w ciele jest trywialny" - prawdy algebraiczne
Index: ChangeLog
===================================================================
RCS file: /cvsroot/mc/mc/edit/ChangeLog,v
retrieving revision 1.188
diff -u -p -r1.188 ChangeLog
--- ChangeLog 4 Feb 2004 23:09:22 -0000 1.188
+++ ChangeLog 26 Mar 2004 17:07:54 -0000
@@ -1,3 +1,27 @@
+2004-03-25 Adam Byrtek <alpha debian org>
+
+ * edit-widget.h (strruct WEdit): New flag rewind. New property
+ load_time.
+ * edit.c (edit_init): Initialize rewind with 0, load_time with
+ current time. (edit_modification): Change rewind flag to 1
+ when lock encountered and user aborts or file modified on disk
+ during editor session and user aborts.
+ (edit_execute_key_command): Rewind last keypress undo
+ information if rewind flag 1.
+ * editcmd.c (edit_save_as_cmd): Check if lock still valid
+ before save. Abort when lock encountered and user aborts. On
+ success update load_time to current time. (edit_save_cmd): The
+ same as above.
+ * editlock.c: Spelling fixes. Sanity check in every function.
+ (edit_lock_file): New dialog option 'Abort'. 'Ignore lock'
+ rephrased to 'Proceed'. (edit_unlock_file): Parts moved to new
+ function edit_lock_check. (edit_lock_check): New function.
+ Check if lock is still valid (eg. not grabbed by sb else).
+ (edit_check_mtime): New function, check if file was modified
+ on disk during current editor session.
+ * editlock.h: New prototypes edit_lock_check,
+ edit_check_mtime.
+
2004-02-04 Pavel Roskin <proski gnu org>
* editcmddef.h: Split CK_No_Command into CK_Insert_Char and
Index: edit-widget.h
===================================================================
RCS file: /cvsroot/mc/mc/edit/edit-widget.h,v
retrieving revision 1.23
diff -u -p -r1.23 edit-widget.h
--- edit-widget.h 29 Oct 2003 08:54:47 -0000 1.23
+++ edit-widget.h 26 Mar 2004 17:07:54 -0000
@@ -55,7 +55,6 @@ struct WEdit {
int overwrite:1; /* Overwrite on type mode (as opposed to insert) */
int modified:1; /* File has been modified and needs saving */
int loading_done:1; /* File has been loaded into the editor */
- int locked:1; /* We hold lock on current file */
int screen_modified:1; /* File has been changed since the last screen draw */
int delete_file:1; /* New file, needs to be deleted unless modified */
int highlight:1; /* There is a selected block */
@@ -64,6 +63,11 @@ struct WEdit {
long curs_line; /* line number of the cursor. */
long start_line; /* line number of the top of the page */
+ /* file integrity infomation */
+ int locked:1; /* We hold lock on current file */
+ int rewind:1; /* Rewind changes on abort */
+ int load_time; /* Time the file was loaded */
+
/* file info */
long total_lines; /* total lines in the file */
long mark1; /* position of highlight start */
Index: edit.c
===================================================================
RCS file: /cvsroot/mc/mc/edit/edit.c,v
retrieving revision 1.87
diff -u -p -r1.87 edit.c
--- edit.c 4 Feb 2004 22:27:58 -0000 1.87
+++ edit.c 26 Mar 2004 17:07:57 -0000
@@ -551,6 +551,8 @@ edit_init (WEdit *edit, int lines, int c
edit->loading_done = 1;
edit->modified = 0;
edit->locked = 0;
+ edit->rewind = 0;
+ edit->load_time = time (NULL);
edit_load_syntax (edit, 0, 0);
{
int color;
@@ -816,12 +818,31 @@ pop_action (WEdit * edit)
/* is called whenever a modification is made by one of the four routines below */
static inline void edit_modification (WEdit * edit)
{
+ int lock;
+
edit->caches_valid = 0;
edit->screen_modified = 1;
- /* raise lock when file modified */
- if (!edit->modified && !edit->delete_file)
- edit->locked = edit_lock_file (edit->filename);
+ if (!edit->modified && !edit->delete_file) {
+ /* Check file mtime, rewind if user aborted */
+ if (!edit_check_mtime (edit->filename, edit->load_time)) {
+ edit->rewind = 1;
+ edit->modified = 1;
+ return;
+ }
+
+ /* Try to fetch lock */
+ lock = edit_lock_file (edit->filename);
+
+ /* User aborted on lock, rewind */
+ if (lock == -1) {
+ edit->rewind = 1;
+ edit->locked = 0;
+ } else {
+ edit->locked = lock;
+ }
+ }
+
edit->modified = 1;
}
@@ -2125,6 +2146,15 @@ void edit_execute_key_command (WEdit *ed
edit_push_key_press (edit);
edit_execute_cmd (edit, command, char_for_insertion);
+
+ /* User aborted (eg. because file is locked), rewind the stack */
+ if (edit->rewind) {
+ edit_do_undo (edit);
+ edit->rewind = 0;
+ /* TODO: Should be done by edit_do_undo */
+ edit->modified = 0;
+ }
+
if (column_highlighting)
edit->force |= REDRAW_PAGE;
}
Index: editcmd.c
===================================================================
RCS file: /cvsroot/mc/mc/edit/editcmd.c,v
retrieving revision 1.102
diff -u -p -r1.102 editcmd.c
--- editcmd.c 27 Nov 2003 10:23:50 -0000 1.102
+++ editcmd.c 26 Mar 2004 17:08:03 -0000
@@ -465,6 +465,9 @@ edit_save_as_cmd (WEdit *edit)
exp = edit_get_save_file (edit->filename, _(" Save As "));
edit_push_action (edit, KEY_PRESS + edit->start_display);
+ /* Check if lock still valid */
+ edit->locked = edit_lock_check (edit->filename);
+
if (exp) {
if (!*exp) {
g_free (exp);
@@ -475,7 +478,7 @@ edit_save_as_cmd (WEdit *edit)
int file;
different_filename = 1;
if ((file = mc_open (exp, O_RDONLY | O_BINARY)) != -1) {
- /* the file exists */
+ /* The file exists */
mc_close (file);
/* Overwrite the current file or cancel the operation */
if (edit_query_dialog2
@@ -488,10 +491,21 @@ edit_save_as_cmd (WEdit *edit)
}
}
save_lock = edit_lock_file (exp);
+ /* User aborted */
+ if (save_lock == -1) {
+ g_free (exp);
+ return 0;
+ }
} else {
- /* filenames equal, check if already locked */
- if (!edit->locked && !edit->delete_file)
+ /* Filenames equal, raise lock if not already raised */
+ if (!edit->locked && !edit->delete_file) {
save_lock = edit_lock_file (exp);
+ /* User aborted */
+ if (save_lock == -1) {
+ g_free (exp);
+ return 0;
+ }
+ }
}
if (edit_save_file (edit, exp)) {
@@ -510,12 +524,13 @@ edit_save_as_cmd (WEdit *edit)
g_free (exp);
edit->modified = 0;
edit->delete_file = 0;
+ edit->load_time = time (NULL);
if (different_filename)
edit_load_syntax (edit, 0, 0);
edit->force |= REDRAW_COMPLETELY;
return 1;
} else {
- /* Failed, so maintain modify (not save) lock */
+ /* On failure maintain lock if locked before */
if (strcmp (edit->filename, exp) && save_lock)
edit_unlock_file (exp);
if (save_lock)
@@ -778,20 +793,30 @@ edit_save_cmd (WEdit *edit)
{
int res, save_lock = 0;
- if (!edit->locked && !edit->delete_file)
+ /* Check if lock is still valid */
+ edit->locked = edit_lock_check (edit->filename);
+
+ /* Try to fetch lock otherwise */
+ if (!edit->locked && !edit->delete_file) {
save_lock = edit_lock_file (edit->filename);
+ /* User aborted */
+ if (save_lock == -1)
+ return 0;
+ }
+
res = edit_save_file (edit, edit->filename);
- /* Maintain modify (not save) lock on failure */
+ /* On failure maintain lock if locked before */
if ((res && edit->locked) || save_lock)
edit->locked = edit_unlock_file (edit->filename);
/* On failure try 'save as', it does locking on its own */
- if (!res)
+ if (!res)
return edit_save_as_cmd (edit);
edit->force |= REDRAW_COMPLETELY;
edit->delete_file = 0;
edit->modified = 0;
+ edit->load_time = time (NULL);
return 1;
}
Index: editlock.c
===================================================================
RCS file: /cvsroot/mc/mc/edit/editlock.c,v
retrieving revision 1.6
diff -u -p -r1.6 editlock.c
--- editlock.c 21 Nov 2003 03:17:18 -0000 1.6
+++ editlock.c 26 Mar 2004 17:08:03 -0000
@@ -1,4 +1,4 @@
-/* editor file locking.
+/* Editor file locking and mtime check.
Copyright (C) 2003 the Free Software Foundation
@@ -66,7 +66,7 @@ lock_build_name (char *fname)
return g_strdup_printf ("%s %s %d", user, host, getpid ());
}
-/* Extract pid from user host domain pid string */
+/* Extract info from user host domain pid string */
static struct lock_s *
lock_extract_info (char *str)
{
@@ -112,9 +112,9 @@ lock_get_info (char *lockfname)
}
-/* Tries to raise file lock
- Returns 1 on success, 0 on failure, -1 if abort
- Warning: Might do screen refresh and lose edit->force */
+/* Try to raise file lock
+ Return 1 if lock raised, 0 if lock ignored, -1 on abort
+ Note: Might do screen refresh and lose edit->force */
int
edit_lock_file (char *fname)
{
@@ -122,12 +122,8 @@ edit_lock_file (char *fname)
struct stat statbuf;
struct lock_s *lockinfo;
- /* Just to be sure (and don't lock new file) */
- if (!fname || !*fname)
- return 0;
-
- /* Locking on VFS is not supported */
- if (!vfs_file_is_local (fname))
+ /* Some sanity checks */
+ if (!fname || !*fname || !vfs_file_is_local (fname))
return 0;
/* Check if already locked */
@@ -148,17 +144,19 @@ edit_lock_file (char *fname)
("File \"%s\" is already being edited\n"
"User: %s\nProcess ID: %d"), fname,
lockinfo->who, lockinfo->pid);
- /* TODO: Implement "Abort" - needs to rewind undo stack */
- switch (edit_query_dialog2
+ switch (edit_query_dialog3
(_("File locked"), msg, _("&Grab lock"),
- _("&Ignore lock"))) {
+ _("&Proceed"), _("&Abort"))) {
case 0:
break;
case 1:
- case -1:
g_free (lockfname);
g_free (msg);
return 0;
+ case 2: case -1:
+ g_free (lockfname);
+ g_free (msg);
+ return -1;
}
g_free (msg);
}
@@ -178,37 +176,77 @@ edit_lock_file (char *fname)
return 1;
}
-/* Lowers file lock if possible
- Always returns 0 to make 'lock = edit_unlock_file (f)' possible */
+/* Lower file lock if possible
+ Always return 0 to make 'lock = edit_unlock_file (f)' possible */
int
edit_unlock_file (char *fname)
{
+ char *lockfname;
+
+ /* Some sanity checks */
+ if (!fname || !*fname || !vfs_file_is_local (fname))
+ return 0;
+
+ /* If lock is ours, remove it */
+ if (edit_lock_check (fname)) {
+ lockfname = g_strconcat (".#", fname, NULL);
+ unlink (lockfname);
+ g_free (lockfname);
+ }
+ return 0;
+}
+
+/* Check if lock is still valid
+ Return 1 if lock is valid, 0 if no lock or lock grabbed */
+int
+edit_lock_check (char *fname)
+{
char *lockfname, *lock;
struct stat statbuf;
- /* Just to be sure */
- if (!fname || !*fname)
+ /* Some sanity checks */
+ if (!fname || !*fname || !vfs_file_is_local (fname))
return 0;
- lockfname = g_strconcat (".#", fname, NULL);
-
/* Check if lock exists */
+ lockfname = g_strconcat (".#", fname, NULL);
if (lstat (lockfname, &statbuf) == -1) {
g_free (lockfname);
return 0;
}
lock = lock_get_info (lockfname);
- if (lock) {
- /* Don't touch if lock is not ours */
- if (lock_extract_info (lock)->pid != getpid ()) {
- g_free (lockfname);
- return 0;
- }
- }
-
- /* Remove lock */
- unlink (lockfname);
g_free (lockfname);
- return 0;
+
+ /* Check if lock is ours */
+ if (strcmp (lock_build_name (fname), lock) != 0)
+ return 0;
+ return 1;
+}
+
+/* Check if file modified on disk during current session
+ Return 1 if ok or user accepted, 0 on abort */
+int
+edit_check_mtime (char *fname, time_t load_time)
+{
+ char *msg;
+ struct stat statbuf;
+
+ if (stat (fname, &statbuf) == 0)
+ if (statbuf.st_mtime > load_time) {
+ msg = g_strdup_printf (_
+ ("File \"%s\" changed on disk.\n"
+ "Do you really want to edit?"), fname);
+ switch (edit_query_dialog2
+ (_("File changed"), msg, _("&Proceed"),
+ _("&Abort"))) {
+ case 0 :
+ g_free (msg);
+ return 1;
+ case 1 : case -1 :
+ g_free (msg);
+ return 0;
+ }
+ }
+ return 1;
}
Index: editlock.h
===================================================================
RCS file: /cvsroot/mc/mc/edit/editlock.h,v
retrieving revision 1.1
diff -u -p -r1.1 editlock.h
--- editlock.h 2 Apr 2003 19:36:10 -0000 1.1
+++ editlock.h 26 Mar 2004 17:08:03 -0000
@@ -3,5 +3,7 @@
int edit_lock_file (char *fname);
int edit_unlock_file (char *fname);
+int edit_lock_check (char *fname);
+int edit_check_mtime (char *fname, time_t load_time);
#endif /* !__EDIT_LOCK_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]