[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] conga/ricci common/Makefile common/XML.cpp com ...



CVSROOT:	/cvs/cluster
Module name:	conga
Branch: 	RHEL5
Changes by:	kupcevic sourceware org	2006-10-23 21:13:22

Modified files:
	ricci/common   : Makefile XML.cpp utils.cpp 
	ricci/modules/cluster/clumon/src/daemon: Monitor.cpp 
	ricci/modules/log: LogParser.cpp 
	ricci/modules/rpm: PackageHandler.cpp 
	ricci/modules/service: ServiceManager.cpp 
	ricci/modules/storage: MountHandler.cpp 
	ricci/ricci    : Ricci.cpp SSLInstance.cpp 
Added files:
	ricci/common   : File.cpp 
	ricci/include  : File.h 

Log message:
	ricci: file handling - agregate file IO into single routine (bz211564)

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/File.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/XML.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/utils.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/include/File.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=NONE&r2=1.1.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.10&r2=1.10.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/log/LogParser.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/rpm/PackageHandler.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.9&r2=1.9.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/service/ServiceManager.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5&r2=1.5.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/storage/MountHandler.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5&r2=1.5.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/ricci/Ricci.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.18&r2=1.18.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/ricci/SSLInstance.cpp.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5&r2=1.5.2.1

/cvs/cluster/conga/ricci/common/File.cpp,v  -->  standard output
revision 1.1.2.1
--- conga/ricci/common/File.cpp
+++ -	2006-10-23 21:13:25.290828000 +0000
@@ -0,0 +1,214 @@
+/*
+  Copyright Red Hat, Inc. 2006
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, 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
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+  MA 02139, USA.
+*/
+/*
+ * Author: Stanko Kupcevic <kupcevic redhat com>
+ */
+
+
+#include "File.h"
+#include <fstream>
+#include <fcntl.h>
+#include <errno.h>
+
+using namespace std;
+
+
+File_pimpl::File_pimpl(void* fs, 
+		       bool& owner) :
+  fs(fs)
+{
+  if (fs == 0)
+    throw String("fs_ptr is null!!!");
+  owner = true;
+}
+
+File_pimpl::~File_pimpl()
+{
+  fstream* ptr = (fstream*) fs;
+  delete ptr;
+}
+
+
+
+File
+File::open(const String& filepath, 
+	   bool rw)
+{
+  if (access(filepath.c_str(), R_OK))
+    throw String("missing file ") + filepath;
+  ios_base::openmode mode = ios_base::in;
+  if (rw)
+    mode |= ios_base::out;
+  
+  counting_auto_ptr<File_pimpl> pimpl;
+  bool ownership_taken = false;
+  fstream* fs = new fstream(filepath.c_str(), mode);
+  try {
+    pimpl = counting_auto_ptr<File_pimpl>(new File_pimpl(fs, ownership_taken));
+  } catch ( ... ) {
+    if (!ownership_taken)
+      delete fs;
+    throw;
+  }
+  return File(pimpl, filepath, rw);
+}
+
+File 
+File::create(const String& filepath, 
+	     bool truncate)
+{
+  int t = ::open(filepath.c_str(), 
+		 O_CREAT|O_RDWR, 
+		 S_IRUSR|S_IWUSR|S_IRGRP);
+  if (t != -1)
+    while (close(t) && errno == EINTR)
+      ;
+  
+  ios_base::openmode mode = ios_base::in;
+  mode |= ios_base::out;
+  if (truncate)
+    mode |= ios_base::trunc;
+  
+  counting_auto_ptr<File_pimpl> pimpl;
+  bool ownership_taken = false;
+  fstream* fs = new fstream(filepath.c_str(), mode);
+  try {
+    pimpl = counting_auto_ptr<File_pimpl>(new File_pimpl(fs, ownership_taken));
+  } catch ( ... ) {
+    if (!ownership_taken)
+      delete fs;
+    throw;
+  }
+  return File(pimpl, filepath, true);
+}
+
+File::File(counting_auto_ptr<File_pimpl> pimpl, 
+	   const String& path,
+	   bool writable) :
+  _mutex(counting_auto_ptr<Mutex>(new Mutex())), 
+  _pimpl(pimpl),
+  _path(path),
+  _writable(writable)
+{
+  if (!((fstream*) _pimpl->fs)->is_open())
+    throw String("unable to open ") + _path;
+  check_failed();
+}
+
+File::~File()
+{
+  if (_writable)
+    ((fstream*) _pimpl->fs)->flush();
+}
+
+String 
+File::path() const
+{
+  return _path;
+}
+
+long 
+File::size() const
+{
+  MutexLocker l(*_mutex);
+  ((fstream*) _pimpl->fs)->seekg(0, ios::end);
+  check_failed();
+  long s = ((fstream*) _pimpl->fs)->tellg();
+  check_failed();
+  if (s < 0)
+    throw String("size of file ") + _path + " is negative!!!";
+  return s;
+}
+
+String 
+File::read() const
+{
+  MutexLocker l(*_mutex);
+  
+  long len = size();
+  auto_ptr<char> buff(new char[len]);
+  ((fstream*) _pimpl->fs)->seekg(0, ios::beg);
+  check_failed();
+  ((fstream*) _pimpl->fs)->read(buff.get(), len);
+  ::shred(buff.get(), len);
+  check_failed();
+  return String(buff.get(), len);
+}
+
+File& 
+File::append(const String& data)
+{
+  MutexLocker l(*_mutex);
+  if (!_writable)
+    throw String("not writable");
+  ((fstream*) _pimpl->fs)->seekp(0, ios::end);
+  check_failed();
+  ((fstream*) _pimpl->fs)->write(data.c_str(), data.size());
+  check_failed();
+  ((fstream*) _pimpl->fs)->flush();
+  check_failed();
+  return *this;
+}
+
+String 
+File::replace(const String& data)
+{
+  MutexLocker l(*_mutex);
+  if (!_writable)
+    throw String("not writable");
+  String old(read());
+  create(_path, true);
+  append(data);
+  return old;
+}
+
+void 
+File::shred()
+{
+  MutexLocker l(*_mutex);
+  if (!_writable)
+    throw String("not writable");
+  unsigned int len = size();
+  ((fstream*) _pimpl->fs)->seekp(0, ios::beg);
+  check_failed();
+  // should use random source (paranoid)
+  // doesn't work on journaled fss anyways
+  ((fstream*) _pimpl->fs)->write(String(len, 'o').c_str(), len);
+  check_failed();
+}
+
+void 
+File::unlink()
+{
+  MutexLocker l(*_mutex);
+  if (::unlink(_path.c_str()))
+    throw String("unlink failed");
+}
+
+File::operator const String () const
+{
+  return read();
+}
+
+void
+File::check_failed() const
+{
+  if (((fstream*) _pimpl->fs)->fail())
+    throw String("IO error");
+}
--- conga/ricci/common/Makefile	2006/06/16 20:44:15	1.6
+++ conga/ricci/common/Makefile	2006/10/23 21:13:20	1.6.2.1
@@ -22,6 +22,7 @@
 	Thread.o \
 	Time.o \
 	utils.o \
+	File.o \
 	XML.o \
 	Socket.o \
 	ServerSocket.o \
--- conga/ricci/common/XML.cpp	2006/10/13 09:36:15	1.6
+++ conga/ricci/common/XML.cpp	2006/10/23 21:13:20	1.6.2.1
@@ -24,12 +24,12 @@
 #include "XML.h"
 #include "Mutex.h"
 #include "utils.h"
+#include "File.h"
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 
 #include <algorithm>
-#include <fstream>
 
 //#include <iostream>
 using namespace std;
@@ -229,25 +229,7 @@
 XMLObject 
 readXML(const String& filename)
 {
-  char* buff = 0;
-  try {
-    if (access(filename.c_str(), R_OK))
-      throw String("missing ") + filename;
-    ifstream is(filename.c_str());
-    is.seekg(0, ios::end);
-    unsigned int length = is.tellg();
-    is.seekg(0, ios::beg);
-    buff = new char[length];
-    is.read(buff, length);
-    String xml_data(buff, length);
-    
-    XMLObject xml(parseXML(xml_data));
-    delete [] buff; buff = 0;
-    return xml;
-  } catch ( ... ) {
-    delete [] buff;
-    throw;
-  }
+  return parseXML(File::open(filename));
 }
 
 
--- conga/ricci/common/utils.cpp	2006/08/14 23:55:48	1.6
+++ conga/ricci/common/utils.cpp	2006/10/23 21:13:20	1.6.2.1
@@ -27,8 +27,7 @@
 #include <openssl/md5.h>
 #include <stdlib.h>
 
-
-#include <iostream>
+//#include <iostream>
 
 
 using namespace std;
@@ -298,7 +297,3 @@
 std::map<String, exec_cache> 
 utils::cache;
 
-
-
-
-
/cvs/cluster/conga/ricci/include/File.h,v  -->  standard output
revision 1.1.2.1
--- conga/ricci/include/File.h
+++ -	2006-10-23 21:13:26.604399000 +0000
@@ -0,0 +1,84 @@
+/*
+  Copyright Red Hat, Inc. 2006
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, 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
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to the
+  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
+  MA 02139, USA.
+*/
+/*
+ * Author: Stanko Kupcevic <kupcevic redhat com>
+ */
+
+
+#ifndef File_h
+#define File_h
+
+#include "String.h"
+#include "counting_auto_ptr.h"
+
+
+class File_pimpl
+{
+ public:
+  File_pimpl(void*, bool&);
+  virtual ~File_pimpl();
+  void* const fs;
+ private:
+  File_pimpl(const File_pimpl&);
+  File_pimpl& operator=(const File_pimpl&);
+};
+
+
+class File
+{
+ public:
+  
+  // throw if non-existant
+  static File open(const String& filepath, 
+		   bool rw=false);
+  // same as open, but create if nonexistant
+  static File create(const String& filepath, 
+		     bool truncate=false);
+  virtual ~File();
+  
+  String path() const;
+  long size() const;
+  
+  String read() const; // return content
+  
+  File& append(const String& data); // append data to the end of file
+  
+  String replace(const String& data); // replace content with data, return old content
+  
+  void shred();
+  void unlink();
+  
+  operator const String () const;
+  
+ private:
+  File(counting_auto_ptr<File_pimpl>,
+       const String& path,
+       bool writable);
+  
+  counting_auto_ptr<Mutex> _mutex;
+  counting_auto_ptr<File_pimpl> _pimpl;
+  const String _path;
+  const bool _writable;
+  
+  void check_failed() const;
+  
+};
+
+
+#endif  // File_h
--- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp	2006/10/16 19:44:30	1.10
+++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp	2006/10/23 21:13:21	1.10.2.1
@@ -31,7 +31,6 @@
 #include <sys/sysinfo.h>
 
 #include <algorithm>
-#include <fstream>
 
 
 using namespace ClusterMonitoring;
--- conga/ricci/modules/log/LogParser.cpp	2006/08/15 00:00:10	1.6
+++ conga/ricci/modules/log/LogParser.cpp	2006/10/23 21:13:21	1.6.2.1
@@ -386,6 +386,8 @@
        iter != files.end();
        iter++) {
     ifstream log(iter->c_str());
+    if (!log.is_open())
+      throw String("failed to open ") + *iter;
     while (log.good()) {
       char buff[1024];
       log.getline(buff, sizeof(buff));
--- conga/ricci/modules/rpm/PackageHandler.cpp	2006/10/12 19:13:11	1.9
+++ conga/ricci/modules/rpm/PackageHandler.cpp	2006/10/23 21:13:21	1.9.2.1
@@ -23,9 +23,9 @@
 
 #include "PackageHandler.h"
 #include "utils.h"
+#include "File.h"
 
 #include <unistd.h>
-#include <fstream>
 
 
 using namespace std;
@@ -645,24 +645,7 @@
 {
   static bool release_set = false;
   if (!release_set) {
-    char* buff = 0;
-    String release;
-    try {
-      ifstream is("/etc/redhat-release");
-      is.seekg(0, ios::end);
-      unsigned int length = is.tellg();
-      is.seekg(0, ios::beg);
-      buff = new char[length];
-      is.read(buff, length);
-      
-      String rel(buff, length);
-      delete [] buff; buff = 0;
-      
-      release = utils::strip(rel);
-    } catch ( ... ) {
-      delete [] buff;
-      throw;
-    }
+    String release(utils::strip(File::open("/etc/redhat-release")));
     
     if (release.find("Nahant") != release.npos)
       RHEL4 = true;
--- conga/ricci/modules/service/ServiceManager.cpp	2006/10/06 03:10:13	1.5
+++ conga/ricci/modules/service/ServiceManager.cpp	2006/10/23 21:13:21	1.5.2.1
@@ -23,9 +23,9 @@
 
 #include "ServiceManager.h"
 #include "utils.h"
+#include "File.h"
 
 #include <vector>
-#include <fstream>
 
 
 using namespace std;
@@ -110,56 +110,43 @@
     String path(INITD_DIR_PATH);
     path += name();
     
-    char* buff = 0;
-    try {
-      ifstream is(path.c_str());
-      is.seekg(0, ios::end);
-      unsigned int length = is.tellg();
-      is.seekg(0, ios::beg);
-      buff = new char[length];
-      is.read(buff, length);
-      String initd(buff, length);
-      
-      list<String> desc_lines;
-      
-      vector<String> lines = utils::split(initd, "\n");
-      for (vector<String>::const_iterator iter = lines.begin();
-	   iter != lines.end();
-	   iter++) {
-	String line(utils::strip(*iter));
-	if (line.empty())
-	  continue;
-	if (line.find(DESC_SIG) != 0)
-	  continue;
-	desc_lines.push_back(line);
-	while (desc_lines.back()[desc_lines.back().size()-1] == '\\' &&
-	       ++iter != lines.end())
-	  if (iter->size())
-	    desc_lines.push_back(*iter);
-	  else
-	    break;
-	break;
-      }
-      
-      String desc;
-      for (list<String>::const_iterator l_iter = desc_lines.begin();
-	   l_iter != desc_lines.end();
-	   l_iter++) {
-	String s = utils::rstrip(*l_iter, "\\");
-	s = utils::lstrip(s, DESC_SIG);
-	s = utils::lstrip(s, "#");
-	s = utils::lstrip(s);
-	desc += s;
-      }
-      
-      _descr = counting_auto_ptr<String>(new String(desc));
-      
-      delete [] buff;
-    } catch ( ... ) {
-      delete [] buff;
-      throw;
+    String initd(File::open(path));
+    
+    list<String> desc_lines;
+    
+    vector<String> lines = utils::split(initd, "\n");
+    for (vector<String>::const_iterator iter = lines.begin();
+	 iter != lines.end();
+	 iter++) {
+      String line(utils::strip(*iter));
+      if (line.empty())
+	continue;
+      if (line.find(DESC_SIG) != 0)
+	continue;
+      desc_lines.push_back(line);
+      while (desc_lines.back()[desc_lines.back().size()-1] == '\\' &&
+	     ++iter != lines.end())
+	if (iter->size())
+	  desc_lines.push_back(*iter);
+	else
+	  break;
+      break;
+    }
+    
+    String desc;
+    for (list<String>::const_iterator l_iter = desc_lines.begin();
+	 l_iter != desc_lines.end();
+	 l_iter++) {
+      String s = utils::rstrip(*l_iter, "\\");
+      s = utils::lstrip(s, DESC_SIG);
+      s = utils::lstrip(s, "#");
+      s = utils::lstrip(s);
+      desc += s;
     }
+    
+    _descr = counting_auto_ptr<String>(new String(desc));
   }
+  
   return *_descr;
 }
 
@@ -681,26 +668,7 @@
 {
   static bool release_set = false;
   if (!release_set) {
-    char* buff = 0;
-    String release;
-    try {
-      ifstream is("/etc/redhat-release");
-      is.seekg(0, ios::end);
-      unsigned int length = is.tellg();
-      is.seekg(0, ios::beg);
-      buff = new char[length];
-      is.read(buff, length);
-      
-      String rel(buff, length);
-      delete [] buff;
-      buff = 0;
-      
-      release = utils::strip(rel);
-    } catch ( ... ) {
-      delete [] buff;
-      throw;
-    }
-    
+    String release(utils::strip(File::open("/etc/redhat-release")));
     if (release.find("Nahant") != release.npos)
       RHEL4 = true;
     else if (release.find("Bordeaux") != release.npos)
@@ -709,7 +677,8 @@
 	     release.find("6") != release.npos)
       // TODO: detect FC6
       FC6 = true;
-    // TODO: detect RHEL5
+    else if (release.find("Tikanga") != release.npos)
+      RHEL5 = true;
     
     release_set = true;
   }
--- conga/ricci/modules/storage/MountHandler.cpp	2006/10/06 03:10:13	1.5
+++ conga/ricci/modules/storage/MountHandler.cpp	2006/10/23 21:13:22	1.5.2.1
@@ -561,8 +561,8 @@
     int ret;
     while ((ret = flock(locker_fd, LOCK_UN)) && errno == EINTR)
       ;
-    if (ret)
-      throw String("unable to unflock fstab");
+    //if (ret)
+    //  throw String("unable to unflock fstab");
     while (close(locker_fd) == -1 && errno == EINTR)
       ;
   }
--- conga/ricci/ricci/Ricci.cpp	2006/10/06 03:10:13	1.18
+++ conga/ricci/ricci/Ricci.cpp	2006/10/23 21:13:22	1.18.2.1
@@ -30,6 +30,7 @@
 #include "QueueLocker.h"
 #include "Time.h"
 #include "XML_tags.h"
+#include "File.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -380,22 +381,11 @@
   QueueLocker lock;
   if (_state != ProcessWorker::st_sched &&
       _state != ProcessWorker::st_prog) {
-    // shred file: 
-    // should use random source (paranoid)
-    // doesn't work on journaled fss anyways
-    ifstream is(_path.c_str());
-    is.seekg(0, ios::end);
-    unsigned int length = is.tellg();
-    is.close();
-    
-    String t(length + 10, 'o');
-    ofstream os(_path.c_str());
-    os.seekp(0);
-    os << t;
-    os.close();
-    
-    // remove file
-    unlink(_path.c_str());
+    try {
+      File f(File::open(_path, true));
+      f.shred();
+      f.unlink();
+    } catch ( ... ) {}
   }
 }
 
@@ -487,26 +477,14 @@
 pair<String, String> 
 clusterinfo()
 {
-  char* buff = 0;
   try {
-    ifstream is("/etc/cluster/cluster.conf");
-    is.seekg(0, ios::end);
-    unsigned int length = is.tellg();
-    is.seekg(0, ios::beg);
-    buff = new char[length];
-    is.read(buff, length);
-    String cluster_conf(buff, length);
-    
-    XMLObject xml(parseXML(cluster_conf));
-    delete [] buff; buff = 0;
-    
+    XMLObject xml(readXML("/etc/cluster/cluster.conf"));
     String name = xml.get_attr("name");
     String alias = xml.get_attr("alias");
     if (utils::strip(alias).empty())
       alias = name;
     return pair<String, String>(name, alias);
   } catch ( ... ) {
-    delete [] buff;
     return pair<String, String>("", "");
   }
 }
@@ -514,22 +492,9 @@
 String 
 os_release()
 {
-  char* buff = 0;
   try {
-    ifstream is("/etc/redhat-release");
-    is.seekg(0, ios::end);
-    unsigned int length = is.tellg();
-    is.seekg(0, ios::beg);
-    buff = new char[length];
-    is.read(buff, length);
-    
-    String rel(buff, length);
-    delete [] buff;
-    buff = 0;
-    
-    return utils::strip(rel);
+    return utils::strip(File::open("/etc/redhat-release"));
   } catch ( ... ) {
-    delete [] buff;
     return "";
   }
 }
--- conga/ricci/ricci/SSLInstance.cpp	2006/08/10 22:53:09	1.5
+++ conga/ricci/ricci/SSLInstance.cpp	2006/10/23 21:13:22	1.5.2.1
@@ -27,6 +27,7 @@
 #include "Time.h"
 #include "Random.h"
 #include "utils.h"
+#include "File.h"
 
 #include <errno.h>
 #include <sys/types.h>
@@ -35,7 +36,6 @@
 #include <unistd.h>
 
 #include <iostream>
-#include <fstream>
 #include <list>
 #include <set>
 
@@ -119,23 +119,11 @@
   for (set<String>::const_iterator iter = files.begin();
        iter != files.end();
        iter++) {
-    char* buff = 0;
     try {
-      ifstream is(iter->c_str());
-      is.seekg(0, ios::end);
-      streamoff length = is.tellg();
-      is.seekg(0, ios::beg);
-      if (length > 10 * 1024)
-	throw String("file too large to be a certificate");
-      buff = new char[length];
-      is.read(buff, length);
-      String cert(buff, length);
-      if (cert.size())
+      String cert(File::open(*iter).read());
+      if (cert.size() && cert.size() < 10 * 1024)
 	authorized_certs.push_back(file_cert(*iter, cert));
-      delete [] buff;
-    } catch ( ... ) {
-      delete [] buff;
-    }
+    } catch ( ... ) {}
   }
 }
 static void 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]