Просмотр исходного кода

* vfs.c: Split garbage collection code into ...
* gc.c: ... this.
* vfs.h: Corresponding code moved ...
* gc.h: ... here.
* Makefile.am: Adjustments for the above.

Pavel Roskin 21 лет назад
Родитель
Сommit
b33f2cbb47
10 измененных файлов с 438 добавлено и 0 удалено
  1. 8 0
      vfs/ChangeLog
  2. 2 0
      vfs/Makefile.am
  3. 1 0
      vfs/cpio.c
  4. 1 0
      vfs/direntry.c
  5. 1 0
      vfs/extfs.c
  6. 1 0
      vfs/fish.c
  7. 1 0
      vfs/ftpfs.c
  8. 395 0
      vfs/gc.c
  9. 27 0
      vfs/gc.h
  10. 1 0
      vfs/sfs.c

+ 8 - 0
vfs/ChangeLog

@@ -1,3 +1,11 @@
+2003-11-07  Pavel Roskin  <proski@gnu.org>
+
+	* vfs.c: Split garbage collection code into ...
+	* gc.c: ... this.
+	* vfs.h: Corresponding code moved ...
+	* gc.h: ... here.
+	* Makefile.am: Adjustments for the above.
+
 2003-11-05  Pavel Roskin  <proski@gnu.org>
 
 	* vfs.c: Eliminate MC_OP.  Reorder other MC_* macros for

+ 2 - 0
vfs/Makefile.am

@@ -16,6 +16,7 @@ BASICFILES = 			\
 	cpio.c			\
 	direntry.c		\
 	extfs.c 		\
+	gc.c	 		\
 	local.c 		\
 	tar.c			\
 	sfs.c			\
@@ -24,6 +25,7 @@ BASICFILES = 			\
 
 VFSHDRS = 			\
 	ftpfs.h 		\
+	gc.h	 		\
 	local.h			\
 	mcfs.h 			\
 	mcfsutil.h 		\

+ 1 - 0
vfs/cpio.c

@@ -20,6 +20,7 @@
 #include <config.h>
 #include <errno.h>
 #include "utilvfs.h"
+#include "gc.h"		/* vfs_rmstamp */
 #include "xdirentry.h"
 
 enum {

+ 1 - 0
vfs/direntry.c

@@ -28,6 +28,7 @@
 #include <errno.h>
 
 #include "utilvfs.h"
+#include "gc.h"		/* vfs_rmstamp */
 #include "xdirentry.h"
 
 #define CALL(x) if (MEDATA->x) MEDATA->x

+ 1 - 0
vfs/extfs.c

@@ -37,6 +37,7 @@
 #include "utilvfs.h"
 #include "../src/execute.h"	/* For shell_execute */
 #include "vfs.h"
+#include "gc.h"		/* vfs_rmstamp */
 
 #undef ERRNOR
 #define ERRNOR(x,y) do { my_errno = x; return y; } while(0)

+ 1 - 0
vfs/fish.c

@@ -43,6 +43,7 @@
 
 #include "xdirentry.h"
 #include "vfs.h"
+#include "gc.h"		/* vfs_add_noncurrent_stamps */
 #include "tcputil.h"
 
 #define FISH_DIRECTORY_TIMEOUT 30 * 60

+ 1 - 0
vfs/ftpfs.c

@@ -72,6 +72,7 @@ What to do with this?
 
 #include "xdirentry.h"
 #include "vfs.h"
+#include "gc.h"		/* vfs_add_noncurrent_stamps */
 #include "tcputil.h"
 #include "../src/setup.h"	/* for load_anon_passwd */
 #include "ftpfs.h"

+ 395 - 0
vfs/gc.c

@@ -0,0 +1,395 @@
+/* Virtual File System grabage collection code
+   Copyright (C) 1995-2003 The Free Software Foundation
+
+   Written by: 1995 Miguel de Icaza
+               1995 Jakub Jelinek
+	       1998 Pavel Machek
+	       2003 Pavel Roskin
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>		/* For atol() */
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <ctype.h>		/* is_digit() */
+
+#include "utilvfs.h"
+#include "gc.h"
+#include "vfs.h"
+
+#include "../src/panel.h"	/* get_current_panel() */
+#include "../src/layout.h"	/* get_current_type() */
+
+
+int vfs_timeout = 60;		/* VFS timeout in seconds */
+
+static struct vfs_stamping *stamps;
+
+
+static void
+vfs_addstamp (struct vfs_class *v, vfsid id, struct vfs_stamping *parent)
+{
+    if (!(v->flags & VFSF_LOCAL) && id != (vfsid) - 1) {
+	struct vfs_stamping *stamp;
+	struct vfs_stamping *last_stamp = NULL;
+
+	for (stamp = stamps; stamp != NULL; stamp = stamp->next) {
+	    if (stamp->v == v && stamp->id == id) {
+		gettimeofday (&(stamp->time), NULL);
+		return;
+	    }
+	    last_stamp = stamp;
+	}
+	stamp = g_new (struct vfs_stamping, 1);
+	stamp->v = v;
+	stamp->id = id;
+	if (parent) {
+	    struct vfs_stamping *st = stamp;
+	    while (parent) {
+		st->parent = g_new (struct vfs_stamping, 1);
+		*st->parent = *parent;
+		parent = parent->parent;
+		st = st->parent;
+	    }
+	    st->parent = 0;
+	} else
+	    stamp->parent = 0;
+
+	gettimeofday (&(stamp->time), NULL);
+	stamp->next = 0;
+
+	if (stamps) {
+	    /* Add to the end */
+	    last_stamp->next = stamp;
+	} else {
+	    /* Add first element */
+	    stamps = stamp;
+	}
+    }
+}
+
+
+void
+vfs_stamp (struct vfs_class *v, vfsid id)
+{
+    struct vfs_stamping *stamp;
+
+    for (stamp = stamps; stamp != NULL; stamp = stamp->next)
+	if (stamp->v == v && stamp->id == id) {
+
+	    gettimeofday (&(stamp->time), NULL);
+	    if (stamp->parent != NULL)
+		vfs_stamp (stamp->parent->v, stamp->parent->id);
+
+	    return;
+	}
+}
+
+
+static void
+vfs_rm_parents (struct vfs_stamping *stamp)
+{
+    struct vfs_stamping *parent;
+
+    while (stamp) {
+	parent = stamp->parent;
+	g_free (stamp);
+	stamp = parent;
+    }
+}
+
+
+void
+vfs_rmstamp (struct vfs_class *v, vfsid id, int removeparents)
+{
+    struct vfs_stamping *stamp, *st1;
+
+    for (stamp = stamps, st1 = NULL; stamp != NULL;
+	 st1 = stamp, stamp = stamp->next)
+	if (stamp->v == v && stamp->id == id) {
+	    if (stamp->parent != NULL) {
+		if (removeparents)
+		    vfs_rmstamp (stamp->parent->v, stamp->parent->id, 1);
+		vfs_rm_parents (stamp->parent);
+		stamp->parent = NULL;
+		continue;	/* rescan the tree */
+	    }
+	    if (st1 == NULL) {
+		stamps = stamp->next;
+	    } else {
+		st1->next = stamp->next;
+	    }
+	    g_free (stamp);
+
+	    return;
+	}
+}
+
+
+vfsid
+vfs_ncs_getid (struct vfs_class *nvfs, const char *dir,
+	       struct vfs_stamping **par)
+{
+    vfsid nvfsid;
+    char *dir1;
+
+    dir1 = concat_dir_and_file (dir, "");
+    nvfsid = (*nvfs->getid) (nvfs, dir1, par);
+    g_free (dir1);
+    return nvfsid;
+}
+
+
+static int
+is_parent (struct vfs_class *nvfs, vfsid nvfsid,
+	   struct vfs_stamping *parent)
+{
+    struct vfs_stamping *stamp;
+
+    for (stamp = parent; stamp; stamp = stamp->parent)
+	if (stamp->v == nvfs && stamp->id == nvfsid)
+	    break;
+
+    return (stamp ? 1 : 0);
+}
+
+
+static void
+vfs_stamp_path (char *path)
+{
+    struct vfs_class *vfs;
+    vfsid id;
+    struct vfs_stamping *par, *stamp;
+
+    vfs = vfs_get_class (path);
+    id = vfs_ncs_getid (vfs, path, &par);
+    vfs_addstamp (vfs, id, par);
+
+    for (stamp = par; stamp != NULL; stamp = stamp->parent)
+	vfs_addstamp (stamp->v, stamp->id, stamp->parent);
+    vfs_rm_parents (par);
+}
+
+
+static void
+_vfs_add_noncurrent_stamps (struct vfs_class *oldvfs, vfsid oldvfsid,
+			    struct vfs_stamping *parent)
+{
+    struct vfs_class *nvfs, *n2vfs, *n3vfs;
+    vfsid nvfsid, n2vfsid, n3vfsid;
+    struct vfs_stamping *par, *stamp;
+    int f;
+
+    /* FIXME: As soon as we convert to multiple panels, this stuff
+       has to change. It works like this: We do not time out the
+       vfs's which are current in any panel and on the other
+       side we add the old directory with all its parents which
+       are not in any panel (if we find such one, we stop adding
+       parents to the time-outing structure. */
+
+    /* There are three directories we have to take care of: current_dir,
+       current_panel->cwd and other_panel->cwd. Athough most of the time either
+       current_dir and current_panel->cwd or current_dir and other_panel->cwd are the
+       same, it's possible that all three are different -- Norbert */
+
+    if (!current_panel)
+	return;
+
+    nvfs = vfs_get_class (vfs_get_current_dir ());
+    nvfsid = vfs_ncs_getid (nvfs, vfs_get_current_dir (), &par);
+    vfs_rmstamp (nvfs, nvfsid, 1);
+
+    f = is_parent (oldvfs, oldvfsid, par);
+    vfs_rm_parents (par);
+    if ((nvfs == oldvfs && nvfsid == oldvfsid) || oldvfsid == (vfsid *) - 1
+	|| f) {
+	return;
+    }
+
+    if (get_current_type () == view_listing) {
+	n2vfs = vfs_get_class (current_panel->cwd);
+	n2vfsid = vfs_ncs_getid (n2vfs, current_panel->cwd, &par);
+	f = is_parent (oldvfs, oldvfsid, par);
+	vfs_rm_parents (par);
+	if ((n2vfs == oldvfs && n2vfsid == oldvfsid) || f)
+	    return;
+    } else {
+	n2vfs = (struct vfs_class *) -1;
+	n2vfsid = (vfsid) - 1;
+    }
+
+    if (get_other_type () == view_listing) {
+	n3vfs = vfs_get_class (other_panel->cwd);
+	n3vfsid = vfs_ncs_getid (n3vfs, other_panel->cwd, &par);
+	f = is_parent (oldvfs, oldvfsid, par);
+	vfs_rm_parents (par);
+	if ((n3vfs == oldvfs && n3vfsid == oldvfsid) || f)
+	    return;
+    } else {
+	n3vfs = (struct vfs_class *) -1;
+	n3vfsid = (vfsid) - 1;
+    }
+
+    if ((*oldvfs->nothingisopen) (oldvfsid)) {
+#if 0				/* need setctl for this */
+	if (oldvfs == &vfs_extfs_ops
+	    && ((extfs_archive *) oldvfsid)->name == 0) {
+	    /* Free the resources immediatly when we leave a mtools fs
+	       ('cd a:') instead of waiting for the vfs-timeout */
+	    (oldvfs->free) (oldvfsid);
+	} else
+#endif
+	    vfs_addstamp (oldvfs, oldvfsid, parent);
+	for (stamp = parent; stamp != NULL; stamp = stamp->parent) {
+	    if ((stamp->v == nvfs && stamp->id == nvfsid)
+		|| (stamp->v == n2vfs && stamp->id == n2vfsid)
+		|| (stamp->v == n3vfs && stamp->id == n3vfsid)
+		|| stamp->id == (vfsid) - 1
+		|| !(*stamp->v->nothingisopen) (stamp->id))
+		break;
+#if 0
+	    if (stamp->v == &vfs_extfs_ops
+		&& ((extfs_archive *) stamp->id)->name == 0) {
+		(stamp->v->free) (stamp->id);
+		vfs_rmstamp (stamp->v, stamp->id, 0);
+	    } else
+#endif
+		vfs_addstamp (stamp->v, stamp->id, stamp->parent);
+	}
+    }
+}
+
+
+void
+vfs_add_noncurrent_stamps (struct vfs_class *oldvfs, vfsid oldvfsid,
+			   struct vfs_stamping *parent)
+{
+    _vfs_add_noncurrent_stamps (oldvfs, oldvfsid, parent);
+    vfs_rm_parents (parent);
+}
+
+
+void
+vfs_add_current_stamps (void)
+{
+    vfs_stamp_path (vfs_get_current_dir ());
+
+    if (current_panel) {
+	if (get_current_type () == view_listing)
+	    vfs_stamp_path (current_panel->cwd);
+    }
+
+    if (other_panel) {
+	if (get_other_type () == view_listing)
+	    vfs_stamp_path (other_panel->cwd);
+    }
+}
+
+
+/* Compare two timeval structures.  Return 0 is t1 is less than t2. */
+static inline int
+timeoutcmp (struct timeval *t1, struct timeval *t2)
+{
+    return ((t1->tv_sec < t2->tv_sec)
+	    || ((t1->tv_sec == t2->tv_sec)
+		&& (t1->tv_usec <= t2->tv_usec)));
+}
+
+
+/* This is called from timeout handler with now = 0, or can be called
+   with now = 1 to force freeing all filesystems that are not in use */
+void
+vfs_expire (int now)
+{
+    static int locked = 0;
+    struct timeval time;
+    struct vfs_stamping *stamp, *st;
+
+    /* Avoid recursive invocation, e.g. when one of the free functions
+       calls message */
+    if (locked)
+	return;
+    locked = 1;
+
+    gettimeofday (&time, NULL);
+    time.tv_sec -= vfs_timeout;
+
+    for (stamp = stamps; stamp != NULL;) {
+	if (now || (timeoutcmp (&stamp->time, &time))) {
+	    st = stamp->next;
+	    (*stamp->v->free) (stamp->id);
+	    vfs_rmstamp (stamp->v, stamp->id, 0);
+	    stamp = st;
+	} else
+	    stamp = stamp->next;
+    }
+    locked = 0;
+}
+
+
+/*
+ * Return the number of seconds remaining to the vfs timeout.
+ * FIXME: The code should be improved to actually return the number of
+ * seconds until the next item times out.
+ */
+int
+vfs_timeouts ()
+{
+    return stamps ? 10 : 0;
+}
+
+
+void
+vfs_timeout_handler (void)
+{
+    vfs_expire (0);
+}
+
+
+void
+vfs_release_path (const char *dir)
+{
+    struct vfs_class *oldvfs;
+    vfsid oldvfsid;
+    struct vfs_stamping *parent;
+
+    oldvfs = vfs_get_class (dir);
+    oldvfsid = vfs_ncs_getid (oldvfs, dir, &parent);
+    vfs_add_noncurrent_stamps (oldvfs, oldvfsid, parent);
+}
+
+
+/* Free all data */
+void
+vfs_gc_done (void)
+{
+    struct vfs_stamping *stamp, *st;
+
+    for (stamp = stamps, stamps = 0; stamp != NULL;) {
+	(*stamp->v->free) (stamp->id);
+	st = stamp->next;
+	g_free (stamp);
+	stamp = st;
+    }
+
+    if (stamps)
+	vfs_rmstamp (stamps->v, stamps->id, 1);
+}

+ 27 - 0
vfs/gc.h

@@ -0,0 +1,27 @@
+#ifndef __GC_H
+#define __GC_H
+
+struct vfs_stamping {
+    struct vfs_class *v;
+    vfsid id;
+    struct vfs_stamping *parent;
+    struct vfs_stamping *next;
+    struct timeval time;
+};
+
+extern int vfs_timeout;
+
+void vfs_stamp (struct vfs_class *, vfsid);
+void vfs_rmstamp (struct vfs_class *, vfsid, int);
+void vfs_add_noncurrent_stamps (struct vfs_class *, vfsid,
+				struct vfs_stamping *);
+void vfs_add_current_stamps (void);
+void vfs_timeout_handler (void);
+void vfs_expire (int);
+int vfs_timeouts (void);
+void vfs_release_path (const char *dir);
+vfsid vfs_ncs_getid (struct vfs_class *nvfs, const char *dir,
+		     struct vfs_stamping **par);
+void vfs_gc_done (void);
+
+#endif				/* __GC_H */

+ 1 - 0
vfs/sfs.c

@@ -22,6 +22,7 @@
 #include "utilvfs.h"
 
 #include "vfs.h"
+#include "gc.h"		/* vfs_add_noncurrent_stamps */
 #include "local.h"
 #include "../src/execute.h"	/* EXECUTE_AS_SHELL */
 

Некоторые файлы не были показаны из-за большого количества измененных файлов