Skip to content

Commit

Permalink
read records from DB for lists at once, not one by one.
Browse files Browse the repository at this point in the history
Keep a runtime cache of dn-id-mapping

Signed-off-by: Arthur Schiwon <[email protected]>
  • Loading branch information
blizzz committed Mar 15, 2020
1 parent 7052803 commit 7d1f0ce
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 39 deletions.
28 changes: 23 additions & 5 deletions apps/user_ldap/lib/Access.php
Original file line number Diff line number Diff line change
Expand Up @@ -878,10 +878,18 @@ public function fetchListOfUsers($filter, $attr, $limit = null, $offset = null,
if(!$forceApplyAttributes) {
$isBackgroundJobModeAjax = $this->config
->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'ajax';
$recordsToUpdate = array_filter($ldapRecords, function($record) use ($isBackgroundJobModeAjax) {
$listOfDNs = array_reduce($ldapRecords, function ($listOfDNs, $entry) {
$listOfDNs[] = $entry['dn'][0];
return $listOfDNs;
}, []);
$idsByDn = $this->userMapper->getListOfIdsByDn($listOfDNs);
$recordsToUpdate = array_filter($ldapRecords, function($record) use ($isBackgroundJobModeAjax, $idsByDn) {
$newlyMapped = false;
$uid = $this->dn2ocname($record['dn'][0], null, true, $newlyMapped, $record);
if(is_string($uid)) {
$uid = $idsByDn[$record['dn'][0]] ?? null;
if($uid === null) {
$uid = $this->dn2ocname($record['dn'][0], null, true, $newlyMapped, $record);
}
if (is_string($uid)) {
$this->cacheUserExists($uid);
}
return ($uid !== false) && ($newlyMapped || $isBackgroundJobModeAjax);
Expand Down Expand Up @@ -932,9 +940,19 @@ public function batchApplyUserAttributes(array $ldapRecords){
*/
public function fetchListOfGroups($filter, $attr, $limit = null, $offset = null) {
$groupRecords = $this->searchGroups($filter, $attr, $limit, $offset);
array_walk($groupRecords, function($record) {

$listOfDNs = array_reduce($groupRecords, function ($listOfDNs, $entry) {
$listOfDNs[] = $entry['dn'][0];
return$listOfDNs;
}, []);
$idsByDn = $this->groupMapper->getListOfIdsByDn($listOfDNs);

array_walk($groupRecords, function($record) use ($idsByDn) {
$newlyMapped = false;
$gid = $this->dn2ocname($record['dn'][0], null, false, $newlyMapped, $record);
$gid = $uidsByDn[$record['dn'][0]] ?? null;
if($gid === null) {
$gid = $this->dn2ocname($record['dn'][0], null, false, $newlyMapped, $record);
}
if(!$newlyMapped && is_string($gid)) {
$this->cacheGroupExists($gid);
}
Expand Down
56 changes: 52 additions & 4 deletions apps/user_ldap/lib/Mapping/AbstractMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@

namespace OCA\User_LDAP\Mapping;

use OC\DB\QueryBuilder\QueryBuilder;

/**
* Class AbstractMapping
*
* @package OCA\User_LDAP\Mapping
*/
abstract class AbstractMapping {
Expand All @@ -39,7 +42,7 @@ abstract class AbstractMapping {
* returns the DB table name which holds the mappings
* @return string
*/
abstract protected function getTableName();
abstract protected function getTableName(bool $includePrefix = true);

/**
* @param \OCP\IDBConnection $dbc
Expand All @@ -48,6 +51,9 @@ public function __construct(\OCP\IDBConnection $dbc) {
$this->dbc = $dbc;
}

/** @var array caches Names (value) by DN (key) */
protected $cache = [];

/**
* checks whether a provided string represents an existing table col
* @param string $col
Expand Down Expand Up @@ -110,7 +116,12 @@ protected function modify($query, $parameters) {
* @return string|false
*/
public function getDNByName($name) {
return $this->getXbyY('ldap_dn', 'owncloud_name', $name);
$dn = array_search($name, $this->cache);
if($dn === false) {
$dn = $this->getXbyY('ldap_dn', 'owncloud_name', $name);
$this->cache[$dn] = $name;
}
return $dn;
}

/**
Expand All @@ -120,13 +131,21 @@ public function getDNByName($name) {
* @return bool
*/
public function setDNbyUUID($fdn, $uuid) {
$oldDn = $this->getDnByUUID($uuid);
$query = $this->dbc->prepare('
UPDATE `' . $this->getTableName() . '`
SET `ldap_dn` = ?
WHERE `directory_uuid` = ?
');

return $this->modify($query, array($fdn, $uuid));
$r = $this->modify($query, [$fdn, $uuid]);

if($r && is_string($oldDn) && isset($this->cache[$oldDn])) {
$this->cache[$fdn] = $this->cache[$oldDn];
unset($this->cache[$oldDn]);
}

return $r;
}

/**
Expand All @@ -145,6 +164,8 @@ public function setUUIDbyDN($uuid, $fdn) {
WHERE `ldap_dn` = ?
');

unset($this->cache[$fdn]);

return $this->modify($query, [$uuid, $fdn]);
}

Expand All @@ -154,7 +175,27 @@ public function setUUIDbyDN($uuid, $fdn) {
* @return string|false
*/
public function getNameByDN($fdn) {
return $this->getXbyY('owncloud_name', 'ldap_dn', $fdn);
if(!isset($this->cache[$fdn])) {
$this->cache[$fdn] = $this->getXbyY('owncloud_name', 'ldap_dn', $fdn);
}
return $this->cache[$fdn];
}

public function getListOfIdsByDn(array $fdns): array {
$qb = $this->dbc->getQueryBuilder();
$qb->select('owncloud_name', 'ldap_dn')
->from($this->getTableName(false))
->where($qb->expr()->in('ldap_dn', $qb->createNamedParameter($fdns, QueryBuilder::PARAM_STR_ARRAY)));
$stmt = $qb->execute();

$results = $stmt->fetchAll(\Doctrine\DBAL\FetchMode::ASSOCIATIVE);
foreach ($results as $key => $entry) {
unset($results[$key]);
$results[$entry['ldap_dn']] = $entry['owncloud_name'];
$this->cache[$entry['ldap_dn']] = $entry['owncloud_name'];
}

return $results;
}

/**
Expand Down Expand Up @@ -190,6 +231,10 @@ public function getNameByUUID($uuid) {
return $this->getXbyY('owncloud_name', 'directory_uuid', $uuid);
}

public function getDnByUUID($uuid) {
return $this->getXbyY('ldap_dn', 'directory_uuid', $uuid);
}

/**
* Gets the UUID based on the provided LDAP DN
* @param string $dn
Expand Down Expand Up @@ -248,6 +293,9 @@ public function map($fdn, $name, $uuid) {

try {
$result = $this->dbc->insertIfNotExist($this->getTableName(), $row);
if((bool)$result === true) {
$this->cache[$fdn] = $name;
}
// insertIfNotExist returns values as int
return (bool)$result;
} catch (\Exception $e) {
Expand Down
5 changes: 3 additions & 2 deletions apps/user_ldap/lib/Mapping/GroupMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ class GroupMapping extends AbstractMapping {
* returns the DB table name which holds the mappings
* @return string
*/
protected function getTableName() {
return '*PREFIX*ldap_group_mapping';
protected function getTableName(bool $includePrefix = true) {
$p = $includePrefix ? '*PREFIX*' : '';
return $p . 'ldap_group_mapping';
}

}
5 changes: 3 additions & 2 deletions apps/user_ldap/lib/Mapping/UserMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ class UserMapping extends AbstractMapping {
* returns the DB table name which holds the mappings
* @return string
*/
protected function getTableName() {
return '*PREFIX*ldap_user_mapping';
protected function getTableName(bool $includePrefix = true) {
$p = $includePrefix ? '*PREFIX*' : '';
return $p . 'ldap_user_mapping';
}

}
Loading

0 comments on commit 7d1f0ce

Please sign in to comment.