LCGDM-666: vfs plugin added
authorAlejandro Álvarez Ayllón <alejandro.alvarez.ayllon@cern.ch>
Mon, 20 Aug 2012 14:26:03 +0000 (14:26 +0000)
committerAlejandro Álvarez Ayllón <alejandro.alvarez.ayllon@cern.ch>
Mon, 20 Aug 2012 14:26:03 +0000 (14:26 +0000)
git-svn-id: https://svn.cern.ch/reps/lcgdm/dmlite-plugins-vfs/trunk@7000 4525493e-7705-40b1-a816-d608a930855b

18 files changed:
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README [new file with mode: 0644]
RELEASE-NOTES [new file with mode: 0644]
cmake/modules/FindDMLite.cmake [new file with mode: 0644]
dist/dmlite-plugins-vfs.spec [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0644]
src/Throw.cpp [new file with mode: 0644]
src/Vfs.cpp [new file with mode: 0644]
src/Vfs.h [new file with mode: 0644]
src/VfsDriver.cpp [new file with mode: 0644]
src/VfsDriver.h [new file with mode: 0644]
src/VfsIO.cpp [new file with mode: 0644]
src/VfsIO.h [new file with mode: 0644]
src/VfsNs.cpp [new file with mode: 0644]
src/VfsNs.h [new file with mode: 0644]
src/VfsPool.cpp [new file with mode: 0644]
src/VfsPool.h [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..dd8a7e3
--- /dev/null
@@ -0,0 +1,34 @@
+cmake_minimum_required (VERSION 2.6)
+
+project (dmlite-plugins-vfs)
+
+# Version
+set(dmlite_MAJOR 0)
+set(dmlite_MINOR 1)
+set(dmlite_PATCH 0)
+
+# Lib suffix
+if (CMAKE_SIZEOF_VOID_P EQUAL 4)
+  set (LIB_SUFFIX ""
+               CACHE STRING "library directory suffix value")
+else (CMAKE_SIZEOF_VOID_P EQUAL 4)
+  set (LIB_SUFFIX "64"
+               CACHE STRING "library directory suffix value")
+endif (CMAKE_SIZEOF_VOID_P EQUAL 4)
+
+# Cmake module directory
+set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
+
+# Packages
+set (BOOST_INCLUDEDIR "/usr/include/boost141") # EPEL5
+find_package (Boost 1.41 REQUIRED)
+find_package (DMLite   REQUIRED)
+
+include_directories (${Boost_INCLUDE_DIR} ${DMLITE_INCLUDE_DIR})
+
+# Definitions
+add_definitions (-D_REENTRANT)
+
+# Subdirectories
+add_subdirectory (src)
+
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..6b0b127
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..bac7469
--- /dev/null
+++ b/README
@@ -0,0 +1,33 @@
+DESCRIPTION
+
+  dmlite provides a set of libraries and plugins that implements
+  the common logic for LCGDM components.
+
+  This package provides the 'adapter' plugin for dmlite, which
+  is an implementation talking to the legacy DPM daemons. 
+
+CONTACT
+
+  Send and email to dpm-users-forum@cern.ch if you have questions
+  regarding the use of this software. To submit patches or suggest improvements
+  send an email to dpm-devel@cern.ch
+
+AUTHORS
+
+  Alejandro Álvarez Ayllón (alejandro.alvarez.ayllon@cern.ch)
+
+LICENSE
+
+  Copyright 2011 the European Middleware Initiative
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/cmake/modules/FindDMLite.cmake b/cmake/modules/FindDMLite.cmake
new file mode 100644 (file)
index 0000000..cb4d931
--- /dev/null
@@ -0,0 +1,41 @@
+# - Try to find DMLITE libraries
+#
+#  DMLITE_FOUND - System has DMLITE
+#  DMLITE_INCLUDE_DIR - The DMLITE include directory
+#  DMLITE_LIBRARIES - The libraries needed to use DMLITE
+#
+# DMLITE_LOCATION
+#   setting this enables search for dmlite libraries / headers in this location
+
+
+# -----------------------------------------------------
+# DMLITE Libraries
+# -----------------------------------------------------
+find_library(DMLITE_LIBRARIES
+    NAMES dmlite
+    HINTS ${DMLITE_LOCATION}/lib ${DMLITE_LOCATION}/lib64 ${DMLITE_LOCATION}/lib32
+    DOC "The main dmlite library"
+)
+if(DMLITE_LIBRARIES)
+    message(STATUS "dmlite library found in ${DMLITE_LIBRARIES}")
+endif()
+
+# -----------------------------------------------------
+# DMLITE Include Directories
+# -----------------------------------------------------
+find_path(DMLITE_INCLUDE_DIR
+    NAMES dmlite/c/dmlite.h dmlite/cpp/dmlite++.h
+    HINTS ${DMLITE_LOCATION} ${DMLITE_LOCATION}/include ${DMLITE_LOCATION}/include/*
+    DOC "The dmlite include directory"
+)
+if(DMLITE_INCLUDE_DIR)
+    message(STATUS "dmlite includes found in ${DMLITE_INCLUDE_DIR}")
+endif()
+
+# -----------------------------------------------------
+# handle the QUIETLY and REQUIRED arguments and set DMLITE_FOUND to TRUE if
+# all listed variables are TRUE
+# -----------------------------------------------------
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(dmlite DEFAULT_MSG DMLITE_LIBRARIES DMLITE_INCLUDE_DIR)
+mark_as_advanced(DMLITE_INCLUDE_DIR DMLITE_LIBRARIES)
diff --git a/dist/dmlite-plugins-vfs.spec b/dist/dmlite-plugins-vfs.spec
new file mode 100644 (file)
index 0000000..4a5a309
--- /dev/null
@@ -0,0 +1,50 @@
+Name:          dmlite-plugins-vfs
+Version:       0.1.0
+Release:       1%{?dist}
+Summary:       Filesystem plugin for dmlite
+Group:         Applications/Internet
+License:       ASL 2.0
+URL:           https://svnweb.cern.ch/trac/lcgdm/wiki/Dpm/Dev/Dmlite
+# The source of this package was pulled from upstream's vcs. Use the
+# following commands to generate the tarball:
+# svn export http://svn.cern.ch/guest/lcgdm/dmlite-plugins-adapter/tags/dmlite-plugins-vfs_0_1_0 dmlite-plugins-vfs-0.1.0
+# tar -czvf dmlite-plugins-vfs-0.1.0.tar.gz dmlite-plugins-vfs-0.1.0
+Source0:       %{name}-%{version}.tar.gz
+Buildroot:     %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+BuildRequires: cmake
+BuildRequires: cppunit-devel
+BuildRequires: dmlite-devel
+
+Requires:      dmlite-libs%{?_isa} = %{version}-%{release}
+
+%description
+This package provides the filesystem plugin for dmlite. This plugin provides both
+a name-space and a trivial pool management implementation.
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+%cmake . -DCMAKE_INSTALL_PREFIX=/
+
+make %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}
+
+make install DESTDIR=%{buildroot}
+
+%clean
+rm -rf %{buildroot}
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/dmlite/plugin_vfs.so
+%doc LICENSE README RELEASE-NOTES
+
+%changelog
+* Mon Aug 20 2012 Alejandro Alvarez <alejandro.alvarez.ayllon@cern.ch> - 0.1.0-1
+- Initial package
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7c21c55
--- /dev/null
@@ -0,0 +1,16 @@
+cmake_minimum_required (VERSION 2.6)
+
+add_library (vfs MODULE Vfs.cpp
+                        VfsDriver.cpp
+                        VfsIO.cpp
+                        VfsNs.cpp
+                        VfsPool.cpp
+                        Throw.cpp
+            )
+
+target_link_libraries (vfs ${DMLITE_LIBRARIES})
+set_target_properties (vfs PROPERTIES PREFIX "plugin_")
+
+install (TARGETS       vfs
+         LIBRARY       DESTINATION usr/lib${LIB_SUFFIX}/dmlite/
+                       COMPONENT   dmlite-plugins)
diff --git a/src/Throw.cpp b/src/Throw.cpp
new file mode 100644 (file)
index 0000000..d7a4e5e
--- /dev/null
@@ -0,0 +1,66 @@
+/// @file   Throw.cpp
+/// @brief  Maps the errno codes to DM_ERROR_*
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#include <dmlite/cpp/exceptions.h>
+#include <errno.h>
+
+#include "Vfs.h"
+
+static int Errno2Code(int err)
+{
+  switch (err)
+  {
+    case EBADF:
+      return DM_BAD_DESCRIPTOR;
+    case EINVAL:
+      return DM_INVALID_VALUE;
+    case ENOMEM:
+      return DM_OUT_OF_MEMORY;
+    case EPERM:
+      return DM_BAD_OPERATION;
+    case ENOENT:
+      return DM_NO_SUCH_FILE;
+    case EACCES:
+      return DM_FORBIDDEN;
+    case EFAULT:
+      return DM_NULL_POINTER;
+    case EEXIST:
+      return DM_EXISTS;
+    case EISDIR:
+      return DM_IS_DIRECTORY;
+    case ENOTDIR:
+      return DM_NOT_DIRECTORY;
+    case ENOSPC:
+      return DM_NO_SPACE_LEFT;
+    case ENAMETOOLONG:
+      return DM_NAME_TOO_LONG;
+    default:
+      return DM_UNKNOWN_ERROR;
+  }
+}
+
+
+
+void dmlite::ThrowExceptionFromErrno(int err, const char* extra) throw(DmException)
+{
+  if (extra == 0) extra = "";
+  throw DmException(Errno2Code(err), "%s: %s", strerror(err), extra);
+}
+
+
+
+int dmlite::wrapCall(int r) throw (DmException)
+{
+  if (r < 0)
+    ThrowExceptionFromErrno(errno);
+  return r;
+}
+
+
+
+void* dmlite::wrapCall(void* p) throw (DmException)
+{
+  if (p == NULL && errno != 0)
+    ThrowExceptionFromErrno(errno);
+  return p;
+}
diff --git a/src/Vfs.cpp b/src/Vfs.cpp
new file mode 100644 (file)
index 0000000..56da6d5
--- /dev/null
@@ -0,0 +1,119 @@
+/// @file   Vfs.cpp
+/// @brief  VFS Plugin entry point.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#include <cstring>
+#include <dmlite/cpp/dmlite.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <sys/utsname.h>
+
+#include "Vfs.h"
+#include "VfsDriver.h"
+#include "VfsIO.h"
+#include "VfsNs.h"
+#include "VfsPool.h"
+
+
+using namespace dmlite;
+
+
+
+VfsFactory::VfsFactory() throw (DmException)
+{
+  struct utsname hname;
+  
+  // Hostname
+  wrapCall(uname(&hname));
+  
+  // Domain
+  struct hostent* hent = gethostbyname(hname.nodename);
+  
+  this->hostName_ = hent->h_name;
+}
+
+
+
+VfsFactory::~VfsFactory()
+{
+  // Nothing
+}
+
+
+
+void VfsFactory::configure(const std::string& key, const std::string& value) throw (DmException)
+{
+  if (key == "TokenPassword") {
+    this->tokenPasswd_ = value;
+  }
+  else if (key == "TokenId") {
+    if (strcasecmp(value.c_str(), "ip") == 0)
+      this->tokenUseIp_ = true;
+    else
+      this->tokenUseIp_ = false;
+  }
+  else if (key == "TokenLife") {
+    this->tokenLife_ = (unsigned)atoi(value.c_str());
+  }
+  else
+    throw DmException(DM_UNKNOWN_OPTION, "Unrecognised option " + key);
+}
+
+
+
+Catalog* VfsFactory::createCatalog(PluginManager*) throw (DmException)
+{
+  return new VfsCatalog(this->hostName_);
+}
+
+
+
+PoolManager* VfsFactory::createPoolManager(PluginManager*) throw (DmException)
+{
+  return new VfsPoolManager(this->hostName_,
+                            this->tokenPasswd_, this->tokenUseIp_,
+                            this->tokenLife_);
+}
+
+
+
+std::string VfsFactory::implementedPool() throw ()
+{
+  return "vfs";
+}
+
+
+
+PoolDriver* VfsFactory::createPoolDriver() throw (DmException)
+{
+  return new VfsPoolDriver(this->hostName_,
+                           this->tokenPasswd_, this->tokenUseIp_,
+                           this->tokenLife_);
+}
+
+
+
+IODriver* VfsFactory::createIODriver(PluginManager*) throw (DmException)
+{
+  return new VfsIODriver(this->tokenPasswd_, this->tokenUseIp_);
+}
+
+
+
+static void registerPluginVfs(PluginManager* pm) throw(DmException)
+{
+  VfsFactory* vfsFactory = new VfsFactory();
+  
+  pm->registerCatalogFactory(vfsFactory);
+  pm->registerPoolManagerFactory(vfsFactory);
+  pm->registerPoolDriverFactory(vfsFactory);
+  pm->registerIOFactory(vfsFactory);
+}
+
+
+
+
+/// This is what the PluginManager looks for
+PluginIdCard plugin_vfs = {
+  PLUGIN_ID_HEADER,
+  registerPluginVfs
+};
diff --git a/src/Vfs.h b/src/Vfs.h
new file mode 100644 (file)
index 0000000..5ca8f9f
--- /dev/null
+++ b/src/Vfs.h
@@ -0,0 +1,48 @@
+/// @file   Vfs.h
+/// @brief  Filesystem plugin.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#ifndef VFS_H
+#define        VFS_H
+
+#include <dmlite/cpp/authn.h>
+#include <dmlite/cpp/catalog.h>
+#include <dmlite/cpp/dmlite.h>
+#include <dmlite/cpp/io.h>
+#include <dmlite/cpp/poolmanager.h>
+
+namespace dmlite {
+
+  /// Concrete factory for DPM wrapper
+  class VfsFactory: public CatalogFactory, public IOFactory,
+                    public PoolManagerFactory, public PoolDriverFactory {
+  public:
+    /// Constructor
+    VfsFactory() throw (DmException);
+    /// Destructor
+    ~VfsFactory();
+
+    void configure(const std::string& key, const std::string& value) throw (DmException);
+
+    Catalog*     createCatalog(PluginManager*)     throw (DmException);
+    PoolManager* createPoolManager(PluginManager*) throw (DmException);
+    
+    std::string  implementedPool(void)  throw();
+    PoolDriver*  createPoolDriver(void) throw (DmException);
+    
+    IODriver*    createIODriver(PluginManager*) throw (DmException);
+
+  protected:  
+    std::string hostName_;
+    
+    std::string tokenPasswd_;
+    bool        tokenUseIp_;
+    unsigned    tokenLife_;
+  };
+
+  void ThrowExceptionFromErrno(int err, const char* extra = 0x00) throw(DmException);
+  int   wrapCall(int   ret) throw (DmException);
+  void* wrapCall(void* ret) throw (DmException);
+
+};
+
+#endif // VFS_H
diff --git a/src/VfsDriver.cpp b/src/VfsDriver.cpp
new file mode 100644 (file)
index 0000000..bb28f0d
--- /dev/null
@@ -0,0 +1,205 @@
+/// @file   FilesystemDriver.cpp
+/// @brief  Regular Filesystem pool
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#include <dmlite/cpp/dmlite.h>
+#include <dmlite/cpp/utils/urls.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/vfs.h>
+
+#include "Vfs.h"
+#include "VfsDriver.h"
+
+using namespace dmlite;
+
+
+
+VfsPoolDriver::VfsPoolDriver(const std::string& host,
+                             const std::string& passwd, bool useIp,
+                             unsigned life):
+    hostName_(host),
+    tokenPasswd_(passwd), tokenUseIp_(useIp), tokenLife_(life)
+{
+  // Nothing
+}
+
+
+
+VfsPoolDriver::~VfsPoolDriver()
+{
+  // Nothing
+}
+
+
+
+std::string VfsPoolDriver::getImplId() const throw ()
+{
+  return "vfs";
+}
+
+
+
+void VfsPoolDriver::setStackInstance(StackInstance* si) throw (DmException)
+{
+  this->si_ = si;
+}
+
+
+
+void VfsPoolDriver::setSecurityContext(const SecurityContext* ctx) throw (DmException)
+{
+  // Id mechanism
+  if (this->tokenUseIp_)
+    this->userId_ = ctx->credentials.remoteAddress;
+  else
+    this->userId_ = ctx->credentials.clientName;
+}
+
+
+
+PoolHandler* VfsPoolDriver::createPoolHandler(const std::string& poolName) throw (DmException)
+{
+  return new VfsPoolHandler(this, poolName);
+}
+
+
+
+void VfsPoolDriver::toBeCreated(const Pool& pool) throw (DmException)
+{
+  // Nothing
+}
+
+
+
+void VfsPoolDriver::justCreated(const Pool& pool) throw (DmException)
+{
+  // Nothing  
+}
+
+
+
+void VfsPoolDriver::update(const Pool& pool) throw (DmException)
+{
+  // Nothing  
+}
+
+
+
+void VfsPoolDriver::toBeDeleted(const Pool& pool) throw (DmException)
+{
+  // Nothing
+}
+
+
+
+VfsPoolHandler::VfsPoolHandler(VfsPoolDriver* driver, const std::string& poolName):
+  driver_(driver), poolName_(poolName)
+{
+  // Nothing
+}
+
+
+
+VfsPoolHandler::~VfsPoolHandler()
+{
+  // Nothing
+}
+
+
+
+std::string VfsPoolHandler::getPoolType(void) throw (DmException)
+{
+  return "vfs";
+}
+
+
+
+std::string VfsPoolHandler::getPoolName(void) throw (DmException)
+{
+  return this->poolName_;
+}
+
+
+
+uint64_t VfsPoolHandler::getTotalSpace(void) throw (DmException)
+{
+  struct statfs fs;
+  
+  wrapCall(statfs("/", &fs));
+  
+  return fs.f_bsize * fs.f_blocks;
+}
+
+
+
+uint64_t VfsPoolHandler::getFreeSpace(void) throw (DmException)
+{
+struct statfs fs;
+  
+  wrapCall(statfs("/", &fs));
+  
+  return fs.f_bsize * fs.f_bfree;
+}
+
+
+
+bool VfsPoolHandler::poolIsAvailable(bool write = true) throw (DmException)
+{
+  return !write;
+}
+
+
+
+bool VfsPoolHandler::replicaIsAvailable(const Replica& replica) throw (DmException)
+{
+  struct stat fstat;
+  
+  return stat(replica.rfn.c_str(), &fstat) == 0;
+}
+
+
+
+Location VfsPoolHandler::whereToRead(const Replica& replica) throw (DmException)
+{
+  struct stat fstat;
+  
+  wrapCall(stat(replica.rfn.c_str(), &fstat));
+  
+  Url rloc(replica.rfn);
+  
+  Chunk single;
+  
+  single.host   = this->driver_->hostName_;
+  single.path   = "/vfs" + rloc.path;
+  single.offset = 0;
+  single.size   = fstat.st_size;
+  
+  single["token"] = dmlite::generateToken(this->driver_->userId_, single.path,
+                                          this->driver_->tokenPasswd_,
+                                          this->driver_->tokenLife_);
+  
+  return Location(1, single);
+}
+
+
+
+void VfsPoolHandler::removeReplica(const Replica& replica) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+Location VfsPoolHandler::whereToWrite(const std::string& sfn) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsPoolHandler::doneWriting(const Replica& replica,
+                                        const Extensible& extras) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
diff --git a/src/VfsDriver.h b/src/VfsDriver.h
new file mode 100644 (file)
index 0000000..e243cd9
--- /dev/null
@@ -0,0 +1,69 @@
+/// @file   VfsDriver.h
+/// @brief  Trivial Filesystem pool
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#ifndef VFSDRIVER_H
+#define        VFSDRIVER_H
+
+#include <dmlite/cpp/pooldriver.h>
+
+namespace dmlite {
+  
+  /// Filesystem driver.
+  class VfsPoolDriver: public PoolDriver {
+  public:
+    VfsPoolDriver(const std::string&, const std::string&, bool, unsigned);
+    ~VfsPoolDriver();
+
+    std::string getImplId() const throw();
+
+    void setStackInstance(StackInstance* si) throw (DmException);
+    void setSecurityContext(const SecurityContext*) throw (DmException);
+
+    PoolHandler* createPoolHandler(const std::string& poolName) throw (DmException);
+
+    void toBeCreated(const Pool& pool) throw (DmException);
+    void justCreated(const Pool& pool) throw (DmException);
+    void update(const Pool& pool) throw (DmException);
+    void toBeDeleted(const Pool& pool) throw (DmException);
+
+  private:
+    friend class VfsPoolHandler;
+
+    StackInstance*         si_;
+
+    std::string hostName_;
+    
+    std::string tokenPasswd_;
+    bool        tokenUseIp_;
+    unsigned    tokenLife_;
+    std::string userId_;
+  };
+
+  class VfsPoolHandler: public PoolHandler {
+  public:
+    VfsPoolHandler(VfsPoolDriver*, const std::string& poolName);
+    ~VfsPoolHandler();
+
+    std::string getPoolType    (void) throw (DmException);
+    std::string getPoolName    (void) throw (DmException);
+    uint64_t    getTotalSpace  (void) throw (DmException);
+    uint64_t    getFreeSpace   (void) throw (DmException);
+    bool        poolIsAvailable(bool) throw (DmException);
+
+    bool     replicaIsAvailable(const Replica& replica) throw (DmException);
+    Location whereToRead       (const Replica& replica) throw (DmException);
+
+    void removeReplica(const Replica&) throw (DmException);
+
+    Location whereToWrite(const std::string&) throw (DmException);
+    void     doneWriting (const Replica&,
+                          const Extensible&) throw (DmException);
+
+  private:
+    VfsPoolDriver* driver_;
+    std::string    poolName_;
+  };
+
+};
+
+#endif // VFSDRIVER_H
diff --git a/src/VfsIO.cpp b/src/VfsIO.cpp
new file mode 100644 (file)
index 0000000..9682a4f
--- /dev/null
@@ -0,0 +1,160 @@
+/// @file   VfsIO.cpp
+/// @brief  IO factory.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#include <dmlite/cpp/dmlite.h>
+#include <errno.h>
+#include "Vfs.h"
+#include "VfsIO.h"
+
+using namespace dmlite;
+
+
+
+VfsIODriver::VfsIODriver(std::string passwd, bool useIp):
+  si_(0), secCtx_(0), passwd_(passwd), useIp_(useIp)
+{
+  // Nothing
+}
+
+
+
+VfsIODriver::~VfsIODriver()
+{
+  // Nothing
+}
+
+
+
+std::string VfsIODriver::getImplId() const throw ()
+{
+  return "VfsIODriver";
+}
+
+
+
+void VfsIODriver::setStackInstance(StackInstance* si) throw (DmException)
+{
+  this->si_ = si;
+}
+
+
+
+void VfsIODriver::setSecurityContext(const SecurityContext* ctx) throw (DmException)
+{
+  this->secCtx_ = ctx;
+}
+
+
+
+IOHandler* VfsIODriver::createIOHandler(const std::string& pfn,
+                                        int openmode,
+                                        const Extensible& extras) throw (DmException)
+{  
+  if (!extras.hasField("token"))
+    throw DmException(DM_FORBIDDEN, "Missing token");
+  
+  std::string userId;
+  if (this->useIp_)
+    userId = this->secCtx_->credentials.remoteAddress;
+  else
+    userId = this->secCtx_->credentials.clientName;
+  
+  if (dmlite::validateToken(extras.getString("token"),
+                            userId,
+                            pfn, this->passwd_,
+                            openmode != O_RDONLY) != kTokenOK)
+    throw DmException(DM_FORBIDDEN, "Token does not validate (using %s)",
+                      this->useIp_?"IP":"DN");
+  
+  // Create
+  return new VfsIOHandler(pfn, openmode);
+}
+
+
+
+void VfsIODriver::doneWriting(const std::string& pfn,
+                              const Extensible& params) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+VfsIOHandler::VfsIOHandler(const std::string& path,
+                           int openmode) throw (DmException):
+  eof_(false), pos_(0)
+{ 
+  std::string real;
+  
+  if (path.compare(0, 5, "/vfs/") != 0)
+    throw DmException(DM_NO_SUCH_FILE, "File not on the /vfs/ namespace");
+  
+  real = path.substr(4);
+  
+  this->fd_ = ::open(real.c_str(), openmode, 0644);
+  if (this->fd_ == -1)
+    throw DmException(DM_NO_SUCH_FILE, "Could not open %s (%d)", path.c_str(), errno);
+}
+
+
+
+VfsIOHandler::~VfsIOHandler()
+{
+  if (this->fd_ != -1)
+    ::close(this->fd_);
+}
+
+
+
+void VfsIOHandler::close() throw (DmException)
+{
+  ::close(this->fd_);
+  this->fd_ = -1;
+}
+
+
+
+size_t VfsIOHandler::read(char* buffer, size_t count) throw (DmException)
+{
+  size_t nbytes = ::read(this->fd_, buffer, count);
+  
+  eof_ = (nbytes < count);
+  
+  return nbytes;
+}
+
+
+
+size_t VfsIOHandler::write(const char* buffer, size_t count) throw (DmException)
+{
+  return ::write(this->fd_, buffer, count);
+}
+
+
+
+void VfsIOHandler::seek(off_t offset, Whence whence) throw (DmException)
+{
+  if ((pos_ = ::lseek(this->fd_, offset, whence)) == ((off_t) - 1))
+    throw DmException(DM_INTERNAL_ERROR, "Could not seek (%d)", errno);
+}
+
+
+
+long VfsIOHandler::tell(void) throw (DmException)
+{
+  return pos_;
+}
+
+
+
+void VfsIOHandler::flush(void) throw (DmException)
+{
+  // Nothing
+}
+
+
+
+bool VfsIOHandler::eof(void) throw (DmException)
+{
+  return eof_;
+}
diff --git a/src/VfsIO.h b/src/VfsIO.h
new file mode 100644 (file)
index 0000000..928f456
--- /dev/null
@@ -0,0 +1,59 @@
+/// @file   VfsIO.h
+/// @brief  IO factory.
+/// @author Alejandro Álvarez Ayllon <aalvarez@cern.ch>
+#ifndef VFSIO_H
+#define        VFSIO_H
+
+#include <dmlite/cpp/dmlite.h>
+#include <dmlite/cpp/io.h>
+#include <fstream>
+
+namespace dmlite {
+
+  class VfsIODriver: public IODriver {
+   public:
+    VfsIODriver(std::string passwd, bool useIp);
+    ~VfsIODriver();
+
+    std::string getImplId() const throw();
+
+    void setStackInstance(StackInstance* si) throw (DmException);
+    void setSecurityContext(const SecurityContext* ctx) throw (DmException);
+
+    IOHandler* createIOHandler(const std::string& pfn, int openmode,
+                              const Extensible& extras) throw (DmException);
+
+    void doneWriting(const std::string& pfn,
+                     const Extensible& params) throw (DmException);
+
+   private:
+    StackInstance*         si_;
+    const SecurityContext* secCtx_;
+
+    std::string passwd_;
+    bool        useIp_;
+  };
+
+  class VfsIOHandler: public IOHandler {
+  public:
+    VfsIOHandler(const std::string& path,
+                 int openmode) throw (DmException);
+    ~VfsIOHandler();
+    
+    void   close(void) throw (DmException);
+    size_t read (char* buffer, size_t count) throw (DmException);
+    size_t write(const char* buffer, size_t count) throw (DmException);
+    void   seek (off_t offset, Whence whence) throw (DmException);
+    off_t  tell (void) throw (DmException);
+    void   flush(void) throw (DmException);
+    bool   eof  (void) throw (DmException);
+
+  protected:
+    int  fd_;
+    bool eof_;
+    long pos_;
+  };
+
+};
+
+#endif // VFSIO_H
diff --git a/src/VfsNs.cpp b/src/VfsNs.cpp
new file mode 100644 (file)
index 0000000..06b8269
--- /dev/null
@@ -0,0 +1,359 @@
+/// @file   VfsNs.cpp
+/// @brief  VFS namespace.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#include <cstdlib>
+#include <cstring>
+#include <dmlite/cpp/dmlite.h>
+#include <dmlite/cpp/utils/urls.h>
+#include <errno.h>
+#include <unistd.h>
+#include <algorithm>
+#include "Vfs.h"
+#include "VfsNs.h"
+
+using namespace dmlite;
+
+
+
+VfsCatalog::VfsCatalog(const std::string& host) throw (DmException): Catalog(),
+        hostName_(host)
+{
+  // Nothing
+}
+
+
+
+VfsCatalog::~VfsCatalog()
+{
+  // Nothing
+}
+
+
+
+std::string VfsCatalog::getImplId() const throw ()
+{
+  return std::string("VfsCatalog");
+}
+
+
+
+void VfsCatalog::setStackInstance(StackInstance* si) throw (DmException)
+{
+  this->si_ = si;
+}
+
+
+
+void VfsCatalog::setSecurityContext(const SecurityContext* ctx) throw (DmException)
+{
+  // TODO
+}
+
+
+
+void VfsCatalog::changeDir(const std::string& path) throw (DmException)
+{
+  wrapCall(chdir(path.c_str()));
+}
+
+
+
+std::string VfsCatalog::getWorkingDir(void) throw (DmException)
+{
+  char buffer[1024];
+  wrapCall(getcwd(buffer, sizeof(buffer)));
+  return std::string(buffer);
+}
+
+
+
+ExtendedStat VfsCatalog::extendedStat(const std::string& path, bool follow) throw (DmException)
+{
+  ExtendedStat xStat;
+  struct stat  fstat;
+
+  if (follow)
+    wrapCall(stat(path.c_str(), &fstat));
+  else
+    wrapCall(lstat(path.c_str(), &fstat));
+  
+  std::vector<std::string> components = Url::splitPath(path);
+  
+  xStat.stat    = fstat;
+  xStat.parent  = 0;  
+  xStat.name    = components.back();
+  xStat.status  = ExtendedStat::kOnline;
+  xStat["pool"] = std::string("vfs");
+
+  return xStat;
+}
+
+
+
+void VfsCatalog::addReplica(const Replica& replica) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::deleteReplica(const Replica& replica) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+std::vector<Replica> VfsCatalog::getReplicas(const std::string& path) throw (DmException)
+{
+  Replica      replica;
+  ExtendedStat xStat = this->extendedStat(path, true);
+  replica.replicaid  = 0;
+  replica.atime      = xStat.stat.st_atime;
+  replica.fileid     = xStat.stat.st_ino;
+  replica.nbaccesses = 0;
+  replica.ptime      = 0;
+  replica.ltime      = 0;
+  replica.type       = Replica::kPermanent;
+  replica.status     = Replica::kAvailable;
+  replica.server     = this->hostName_;
+  replica["pool"]    = std::string("vfs");
+  
+  std::string wd = this->getWorkingDir();
+  if (wd.empty() || path[0] == '/')
+    replica.rfn = path;
+  else
+    replica.rfn = wd + "/" + path;
+
+  return std::vector<Replica>(1, replica);
+}
+
+
+
+void VfsCatalog::symlink(const std::string& oldpath, const std::string& newpath) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+std::string VfsCatalog::readLink(const std::string& path) throw (DmException)
+{
+  char buf[PATH_MAX];
+  wrapCall(readlink(path.c_str(), buf, sizeof(buf)));
+  return buf;
+}
+
+
+
+void VfsCatalog::unlink(const std::string& path) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::create(const std::string& path, mode_t mode) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+mode_t VfsCatalog::umask(mode_t mask) throw ()
+{
+  return umask(mask);
+}
+
+
+
+void VfsCatalog::setMode(const std::string& path, mode_t mode) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::setOwner(const std::string& path, uid_t newUid, gid_t newGid, bool followSymLink) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::setSize(const std::string& path, size_t newSize) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::setChecksum(const std::string& path,
+                                      const std::string& csumtype,
+                                      const std::string& csumvalue) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");;
+}
+
+
+
+void VfsCatalog::setAcl(const std::string& path, const Acl& acl) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::utime(const std::string& path, const struct utimbuf* buf) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+std::string VfsCatalog::getComment(const std::string& path) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED, "VfsCatalog does not implement comments");
+}
+
+
+
+void VfsCatalog::setComment(const std::string& path, const std::string& comment) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED, "VfsCatalog does not implement comments");
+}
+
+
+
+void VfsCatalog::setGuid(const std::string&, const std::string&) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED, "VfsCatalog does not support setting the GUID");
+}
+
+
+
+void VfsCatalog::updateExtendedAttributes(const std::string& path,
+                                                const Extensible& attr) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED, "VfsCatalog does not support extended attributes");
+}
+
+
+
+Directory* VfsCatalog::openDir(const std::string& path) throw (DmException)
+{
+  PrivateDir *privateDir;
+
+  privateDir = new PrivateDir();
+  privateDir->path = path;
+  privateDir->dir  = opendir(path.c_str());
+  if (privateDir->dir == NULL) {
+    delete privateDir;
+    ThrowExceptionFromErrno(errno);
+    return NULL;
+  }
+
+  return privateDir;
+}
+
+
+
+void VfsCatalog::closeDir(Directory* dir) throw (DmException)
+{
+  int         r;
+  PrivateDir *privateDir = dynamic_cast<PrivateDir*>(dir);
+
+  if (privateDir == NULL)
+    throw DmException(DM_NULL_POINTER, "Tried to close a null directory");
+
+  r = closedir(privateDir->dir);
+  delete privateDir;
+
+  wrapCall(r);
+}
+
+
+
+struct dirent* VfsCatalog::readDir(Directory* dir) throw (DmException)
+{
+  PrivateDir *privateDir = dynamic_cast<PrivateDir*>(dir);
+
+  if (privateDir == NULL)
+    throw DmException(DM_NULL_POINTER, "Tried to read a null directory");
+
+  return static_cast<struct dirent*>(wrapCall(readdir(privateDir->dir)));
+}
+
+
+
+ExtendedStat* VfsCatalog::readDirx(Directory* dir) throw (DmException)
+{
+  PrivateDir  *privateDir = static_cast<PrivateDir*>(dir);
+  
+  struct dirent *ent = this->readDir(dir);
+  if (ent == NULL) return NULL;
+  
+  struct stat fstat;
+  
+  wrapCall(fstatat(dirfd(privateDir->dir), ent->d_name,
+                   &fstat, AT_SYMLINK_NOFOLLOW));
+  
+  privateDir->stat.stat   = fstat;
+  privateDir->stat.name   = ent->d_name;
+  privateDir->stat.status = ExtendedStat::kOnline;
+  privateDir->stat.parent = 0;
+  
+  return &(privateDir->stat);
+}
+
+
+
+void VfsCatalog::makeDir(const std::string& path, mode_t mode) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::rename(const std::string& oldPath, const std::string& newPath) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+void VfsCatalog::removeDir(const std::string& path) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
+
+
+
+Replica VfsCatalog::getReplica(const std::string& rfn) throw (DmException)
+{
+  Replica replica;
+  struct stat fstat;
+  
+  wrapCall(stat(rfn.c_str(), &fstat));
+  
+  replica.atime      = fstat.st_atime;
+  replica.fileid     = fstat.st_ino;
+  replica.ltime      = 0;
+  replica.nbaccesses = 0;
+  replica.ptime      = 0;
+  replica.replicaid  = 0;
+  replica.rfn        = rfn;
+  replica.server     = this->hostName_;
+  replica.status     = Replica::kAvailable;
+  replica.type       = Replica::kPermanent;
+  
+  return replica;
+}
+        
+
+
+void VfsCatalog::updateReplica(const Replica& replica) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
diff --git a/src/VfsNs.h b/src/VfsNs.h
new file mode 100644 (file)
index 0000000..18241ec
--- /dev/null
@@ -0,0 +1,100 @@
+/// @file   VfsNs.h
+/// @brief  VFS namespace.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#ifndef VFSNS_H
+#define        VFSNS_H
+
+#include <dirent.h>
+#include <dmlite/cpp/catalog.h>
+
+
+namespace dmlite {
+
+  /// @brief The private structure used by NsDummy to handle
+  ///        openDir/readDir/closeDir
+  struct PrivateDir: public Directory {
+    virtual ~PrivateDir() {};
+    std::string  path; ///< Directory opened
+    DIR         *dir;  ///< Used for calls to the dpns API.
+    ExtendedStat stat; ///< Where the data is actually stored.
+  };
+
+  /// Catalog implemented as a wrapper around Cns API
+  class VfsCatalog: public Catalog
+  {
+   public:
+    /// Constructor
+    /// @param retryLimit Limit of retrials.
+    VfsCatalog(const std::string& host) throw (DmException);
+
+    /// Destructor
+    ~VfsCatalog();
+
+    // Overloading
+    std::string getImplId(void) const throw ();
+
+    void setStackInstance(StackInstance* si) throw (DmException);
+    void setSecurityContext(const SecurityContext*) throw (DmException);
+
+    void        changeDir     (const std::string&) throw (DmException);
+    std::string getWorkingDir (void)               throw (DmException);
+
+    ExtendedStat extendedStat(const std::string&, bool) throw (DmException);
+
+    SymLink readLink(ino_t) throw (DmException);
+
+    void addReplica   (const Replica&) throw (DmException);
+    void deleteReplica(const Replica&) throw (DmException);
+    std::vector<Replica> getReplicas(const std::string&) throw (DmException);
+
+    void        symlink (const std::string&, const std::string&) throw (DmException);
+    std::string readLink(const std::string& path) throw (DmException);
+    
+    void unlink(const std::string&)                     throw (DmException);
+
+    void create(const std::string&, mode_t) throw (DmException);
+
+    mode_t umask   (mode_t)                           throw ();
+    void   setMode (const std::string&, mode_t)       throw (DmException);
+    void   setOwner(const std::string&, uid_t, gid_t, bool) throw (DmException);
+
+    void setSize    (const std::string&, size_t) throw (DmException);
+    void setChecksum(const std::string&,
+                    const std::string&, const std::string&) throw (DmException);
+
+    void setAcl(const std::string&, const Acl&) throw (DmException);
+
+    void utime(const std::string&, const struct utimbuf*) throw (DmException);
+
+    std::string getComment(const std::string&) throw (DmException);
+    void        setComment(const std::string&,
+                          const std::string&) throw (DmException);
+
+    void setGuid(const std::string&, const std::string&) throw (DmException);
+
+    void updateExtendedAttributes(const std::string&,
+                                  const Extensible&) throw (DmException);
+    
+    Directory* openDir (const std::string&) throw (DmException);
+    void       closeDir(Directory*)         throw (DmException);
+
+    struct dirent* readDir (Directory*) throw (DmException);
+    ExtendedStat*  readDirx(Directory*) throw (DmException);
+
+    void makeDir(const std::string&, mode_t) throw (DmException);
+
+    void rename     (const std::string&, const std::string&) throw (DmException);
+    void removeDir  (const std::string&)                     throw (DmException);
+
+    Replica getReplica   (const std::string& rfn)        throw (DmException);
+    void    updateReplica(const Replica& replica) throw (DmException);
+
+   protected:
+    StackInstance* si_;
+    
+    std::string hostName_;
+  };
+
+};
+
+#endif // VFSNS_H
diff --git a/src/VfsPool.cpp b/src/VfsPool.cpp
new file mode 100644 (file)
index 0000000..5062f28
--- /dev/null
@@ -0,0 +1,157 @@
+/// @file   VfsPool.cpp
+/// @brief  Trivial pool implementation.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <dmlite/common/errno.h>
+#include <dmlite/cpp/utils/urls.h>
+#include <map>
+#include <vector>
+
+#include "Vfs.h"
+#include "VfsPool.h"
+
+using namespace dmlite;
+
+
+
+VfsPoolManager::VfsPoolManager(const std::string& host,
+                               const std::string& passwd,
+                               bool useIp,
+                               unsigned life) throw (DmException):
+  hostName_(host), tokenPasswd_(passwd), tokenUseIp_(useIp),
+  tokenLife_(life), userId_("")
+{
+  // Nothing
+}
+
+
+
+VfsPoolManager::~VfsPoolManager()
+{
+  // Nothing
+}
+
+
+
+std::string VfsPoolManager::getImplId() const throw()
+{
+  return std::string("VfsPoolManager");
+}
+
+
+
+void VfsPoolManager::setStackInstance(StackInstance* si) throw (DmException)
+{
+  // Nothing
+  this->si_ = si;
+}
+
+
+
+void VfsPoolManager::setSecurityContext(const SecurityContext* ctx) throw (DmException)
+{
+  if (this->tokenUseIp_)
+    this->userId_ = ctx->credentials.remoteAddress;
+  else
+    this->userId_ = ctx->credentials.clientName;
+}
+
+
+
+std::vector<Pool> VfsPoolManager::getPools(PoolAvailability availability) throw (DmException)
+{
+  Pool pool;
+  
+  pool.name = "vfs";
+  pool.type = "vfs";
+  
+  switch (availability)
+  {
+    case kForBoth: case kForWrite:
+    case kNone:
+      break;
+    default:
+      return std::vector<Pool>(1, pool);
+  }
+  
+  return std::vector<Pool>();
+}
+
+
+
+Pool VfsPoolManager::getPool(const std::string& poolname) throw (DmException)
+{
+  if (poolname != "vfs")  
+    throw DmException(DM_NO_SUCH_POOL, "Pool " + poolname + " not found");
+
+  Pool pool;
+  
+  pool.name = "vfs";
+  pool.type = "vfs";
+  
+  return pool;
+}
+
+
+
+void VfsPoolManager::newPool(const Pool&) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED,
+                    "VfsPoolManager::newPool not implemented");
+}
+
+
+
+void VfsPoolManager::updatePool(const Pool&) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED,
+                    "VfsPoolManager::updatePool not implemented");
+}
+
+
+
+void VfsPoolManager::deletePool(const Pool&) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED,
+                    "VfsPoolManager::deletePool not implemented");
+}
+
+
+
+Location VfsPoolManager::whereToRead(const std::string& path) throw (DmException)
+{
+  struct stat fstat;
+  
+  wrapCall(stat(path.c_str(), &fstat));
+  
+  Url rloc(path);
+  
+  Chunk single;
+  
+  single.host   = this->hostName_;
+  single.path   = "/vfs" + rloc.path;
+  single.offset = 0;
+  single.size   = fstat.st_size;
+  
+  single["token"] = dmlite::generateToken(this->userId_, single.path,
+                                          this->tokenPasswd_,
+                                          this->tokenLife_);
+  
+  return Location(1, single);
+}
+
+
+
+Location VfsPoolManager::whereToRead(ino_t) throw (DmException)
+{
+  throw DmException(DM_NOT_IMPLEMENTED, "VfsPoolManager: Access by inode not supported");
+}
+
+
+
+Location VfsPoolManager::whereToWrite(const std::string& path) throw (DmException)
+{
+  throw DmException(DM_FORBIDDEN, "Write mode not supported");
+}
diff --git a/src/VfsPool.h b/src/VfsPool.h
new file mode 100644 (file)
index 0000000..b5d1243
--- /dev/null
@@ -0,0 +1,45 @@
+/// @file   VfsPool.h
+/// @brief  Trivial pool implementation.
+/// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
+#ifndef VFSPOOL_H
+#define        VFSPOOL_H
+
+#include <dmlite/cpp/poolmanager.h>
+
+namespace dmlite {
+
+  class VfsPoolManager: public PoolManager {
+  public:
+    VfsPoolManager(const std::string&, const std::string&, bool, unsigned) throw (DmException);
+    ~VfsPoolManager();
+
+    std::string getImplId() const throw ();
+
+    void setStackInstance(StackInstance* si) throw (DmException);
+    void setSecurityContext(const SecurityContext*) throw (DmException);
+
+    std::vector<Pool> getPools(PoolAvailability availability = kAny) throw (DmException);
+    Pool getPool(const std::string&) throw (DmException);
+
+    void newPool(const Pool& pool) throw (DmException);
+    void updatePool(const Pool& pool) throw (DmException);
+    void deletePool(const Pool& pool) throw (DmException);
+
+    Location whereToRead (const std::string& path) throw (DmException);
+    Location whereToRead (ino_t inode)             throw (DmException);
+    Location whereToWrite(const std::string& path) throw (DmException);
+
+  private:
+    StackInstance* si_;
+    
+    std::string hostName_;
+
+    std::string tokenPasswd_;
+    bool        tokenUseIp_;
+    unsigned    tokenLife_;
+    std::string userId_;
+  };
+
+};
+
+#endif // VFSPOOL_H