Permalink
Browse files

Merge branch 'feature-chdbloader' into develop

  • Loading branch information...
2 parents c6e4ed4 + 6d10dcb commit def465ef0d44e0bb41f0b9003d55b695b50784f9 @zyxist zyxist committed Jul 11, 2011
View
@@ -7,5 +7,6 @@ build.properties
tests/cache/*
tests/coverage/*
tests/bootstrap.php
+tests/data/classMap.chdb
catalog.xml
-nbproject/*
+nbproject/*
@@ -0,0 +1,197 @@
+<?php
+/*
+ * OPEN POWER LIBS <http://www.invenzzia.org>
+ *
+ * This file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE. It is also available through
+ * WWW at this URL: <http://www.invenzzia.org/license/new-bsd>
+ *
+ * Copyright (c) Invenzzia Group <http://www.invenzzia.org>
+ * and other contributors. See website for details.
+ */
+namespace Opl\Autoloader;
+use chdb;
+use DomainException;
+use Exception;
+use RuntimeException;
+
+/**
+ * A modification of the <tt>ClassMapLoader</tt> which allows to use
+ * the <tt>chdb</tt> (http://pecl.php.net/package/chdb) caching extension
+ * to store the class maps.
+ *
+ * @author Tomasz Jędrzejewski
+ * @copyright Invenzzia Group <http://www.invenzzia.org/> and contributors.
+ * @license http://www.invenzzia.org/license/new-bsd New BSD License
+ */
+class ChdbLoader
+{
+ /**
+ * The default autoloader path.
+ * @var string
+ */
+ private $defaultPath = '';
+
+ /**
+ * The list of available top-level namespaces.
+ * @var array
+ */
+ private $namespaces = array();
+ /**
+ * The loaded class map.
+ * @var array
+ * @internal
+ */
+ protected $classMap;
+ /**
+ * The location where the class map is stored.
+ * @var string
+ * @internal
+ */
+ protected $classMapLocation;
+
+ /**
+ * Creates the class map loader and loads the map into the memory.
+ * The map must be constructed with the command line interface.
+ *
+ * @param string $defaultPath The default location path used for newly registered namespaces
+ * @param string $classMapLocation The chdb mapped memory file with the class map.
+ */
+ public function __construct($defaultPath, $classMapLocation)
+ {
+ $this->setDefaultPath($defaultPath);
+ $this->classMapLocation = $classMapLocation;
+ try
+ {
+ $this->classMap = new chdb($this->classMapLocation);
+ }
+ catch(Exception $exception)
+ {
+ throw new RuntimeException('Cannot find a class map under the specified location.');
+ }
+ } // end __construct();
+
+ /**
+ * Registers a new top-level namespace to match. If no path is specified, the current
+ * default path is taken.
+ *
+ * @throws RuntimeException
+ * @param string $namespace The namespace name to add.
+ * @param string $path The path to the namespace.
+ */
+ public function addNamespace($namespace, $path = null)
+ {
+ if(isset($this->namespaces[(string)$namespace]))
+ {
+ throw new DomainException('The namespace '.$namespace.' is already added.');
+ }
+ if($path !== null)
+ {
+ $length = strlen($path);
+ if($length == 0 || $path[$length - 1] != '/')
+ {
+ $path .= '/';
+ }
+ $this->namespaces[(string)$namespace] = $path;
+ }
+ else
+ {
+ $this->namespaces[(string)$namespace] = $this->defaultPath;
+ }
+ } // end addNamespace();
+
+ /**
+ * Checks if the specified namespace is available.
+ *
+ * @param string $namespace The namespace name to check.
+ */
+ public function hasNamespace($namespace)
+ {
+ return isset($this->namespaces[(string)$namespace]);
+ } // end hasNamespace();
+
+ /**
+ * Removes a registered top-level namespace.
+ *
+ * @throws RuntimeException
+ * @param string $namespace The namespace name to remove.
+ */
+ public function removeNamespace($namespace)
+ {
+ if(!isset($this->namespaces[(string)$namespace]))
+ {
+ throw new DomainException('The namespace '.$namespace.' is not available.');
+ }
+ unset($this->namespaces[(string)$namespace]);
+ } // end removeNamespace();
+
+ /**
+ * Sets the default path used by the namespaces. Note that it does not affect
+ * the already added namespaces.
+ *
+ * @param string $defaultPath The new default path.
+ */
+ public function setDefaultPath($defaultPath)
+ {
+ $length = strlen($defaultPath);
+ if($length == 0 || $defaultPath[$length - 1] != '/')
+ {
+ $defaultPath .= '/';
+ }
+ $this->defaultPath = $defaultPath;
+ } // end setDefaultPath();
+
+ /**
+ * Returns the default path used by the namespaces.
+ *
+ * @return string The current default path.
+ */
+ public function getDefaultPath()
+ {
+ return $this->defaultPath;
+ } // end getDefaultPath();
+
+ /**
+ * Returns the current class map location.
+ *
+ * @return string
+ */
+ public function getClassMapLocation()
+ {
+ return $this->classMapLocation;
+ } // end getClassMapLocation();
+
+ /**
+ * Installs this class loader on the SPL autoload stack.
+ */
+ public function register()
+ {
+ spl_autoload_register(array($this, 'loadClass'));
+ } // end register();
+
+ /**
+ * Uninstalls this class loader from the SPL autoloader stack.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ } // end unregister();
+
+ /**
+ * Attempts to load the specified class from a file.
+ *
+ * @param string $className The class name.
+ * @return boolean
+ */
+ public function loadClass($className)
+ {
+ $class = $this->classMap->get($className);
+ if(null === $class)
+ {
+ return false;
+ }
+ $class = unserialize($class);
+ require($this->namespaces[$class[0]].$class[1]);
+ return true;
+ } // end loadClass();
+} // end ChdbLoader;
@@ -40,12 +40,16 @@ protected function configure()
$this->setDefinition(array(
new InputArgument('configuration', InputArgument::REQUIRED, 'The Open Power Autoloader configuration'),
))
+ ->addOption('type', 't', InputOption::VALUE_REQUIRED, 'Map type: \'serialized\' or \'chdb\'')
->setName('opl:autoloader:build-class-map')
->setDescription('Generates the class map for the ClassMapLoader')
->setHelp(<<<EOF
The <info>autoloader:class-map:build</info> command is responsible for building
the class maps for the ClassMapLoader autoloader. The configuration file is an
XML document. Please refer to the OPA user manual to get to know more.
+
+The extra option \'type\' defines the output format: either a serialized array or
+a memory-mapped file for \'chdb\' PECL extension (Unix only).
EOF
);
} // end configure();
@@ -65,10 +69,34 @@ protected function execute(InputInterface $input, OutputInterface $output)
return;
}
- if(!$configuration->hasFile('serialized-class-map'))
+ $type = $input->getOption('type');
+ if(empty($type))
+ {
+ $type = 'serialized';
+ }
+ if($type != 'serialized' && $type != 'chdb')
+ {
+ $output->writeln('<error>Invalid type specified.</error>');
+ return;
+ }
+ switch($type)
+ {
+ case 'serialized':
+ $optionName = 'serialized-class-map';
+ break;
+ case 'chdb':
+ if(!extension_loaded('chdb'))
+ {
+ $output->writeln('<error>chdb extension is not installed.</error>');
+ return;
+ }
+ $optionName = 'chdb-class-map';
+ }
+
+ if(!$configuration->hasFile($optionName))
{
- $output->writeln('<error>Serialized class map file definition is missing in the configuration file!</error>');
- $output->writeln('Hint: add \'serialized-class-map\' file type to export-files section.');
+ $output->writeln('<error>The class map file definition is missing in the configuration file!</error>');
+ $output->writeln('Hint: add \''.$optionName.'\' file type to export-files section.');
return;
}
@@ -87,7 +115,23 @@ protected function execute(InputInterface $input, OutputInterface $output)
$output->writeln(preg_replace('/^(([^\:]+)\:) (.*)$/', '<error>Warning: $1</error> $3', $error));
}
- file_put_contents($configuration->getFile('serialized-class-map'), serialize($builder->getMap()));
- $output->writeln('<info>Map saved as:</info> '.$configuration->getFile('serialized-class-map'));
+ if($type == 'serialized')
+ {
+ file_put_contents($configuration->getFile($optionName), serialize($builder->getMap()));
+ }
+ else
+ {
+ $fileName = $configuration->getFile($optionName);
+
+ $map = array();
+ foreach($builder->getMap() as $className => $data)
+ {
+ $map[$className] = serialize($data);
+ }
+
+ chdb_create($fileName.'.0', $map);
+ rename($fileName.'.0', $fileName);
+ }
+ $output->writeln('<info>Map saved as:</info> '.$configuration->getFile($optionName));
} // end execute();
} // end ClassMapBuild;
@@ -15,6 +15,7 @@ public static function suite()
$suite = new AllTests('TestSuite');
$suite->addTestSuite('TestSuite\\ApcLoaderTest');
+ $suite->addTestSuite('TestSuite\\ChdbLoaderTest');
$suite->addTestSuite('TestSuite\\ExceptionTest');
$suite->addTestSuite('TestSuite\\GenericLoaderTest');
$suite->addTestSuite('TestSuite\\ClassMapLoaderTest');
Oops, something went wrong.

0 comments on commit def465e

Please sign in to comment.