diff --git a/wire/core/FieldtypeMulti.php b/wire/core/FieldtypeMulti.php index 0be85ba4..fcf172ee 100644 --- a/wire/core/FieldtypeMulti.php +++ b/wire/core/FieldtypeMulti.php @@ -657,17 +657,16 @@ abstract class FieldtypeMulti extends Fieldtype { if(count($primaryKeys) !== 1) throw new WireException("savePageFieldRows() can only be used on fieldtypes with 1 primary key"); $value = $this->setupPageFieldRows($page, $field, $value); - $database = $this->wire('database'); + $database = $this->wire()->database; $table = $database->escapeTable($info['table']); $primaryKey = $database->escapeCol(reset($primaryKeys)); $hasInserts = false; $sort = null; $numSaved = 0; + $locked = false; // sleep the values for storage $sleepValue = $this->sleepValue($page, $field, $value); - - $this->lockForWriting($field); if(isset($schema['sort'])) { // determine if there are any INSERTs and what the next sort value(s) should be @@ -680,6 +679,8 @@ abstract class FieldtypeMulti extends Fieldtype { if(isset($v['sort']) && $v['sort'] > $maxSort) $maxSort = $v['sort']; } if($hasInserts) { + // we will need a locked table for inserts + if(!$locked) $locked = $this->lockForWriting($field); // determine max sort value for new items inserted $sort = $this->getMaxColumnValue($page, $field, 'sort', -1); if($maxSort > $sort) $sort = $maxSort; @@ -724,11 +725,16 @@ abstract class FieldtypeMulti extends Fieldtype { try { if($query->execute()) $numSaved++; } catch(\Exception $e) { - $this->error($e->getMessage(), $this->wire('user')->isSuperuser() ? Notice::logOnly : Notice::log); + $this->trackException($e, false); + if($this->wire()->user->isSuperuser()) { + $this->error($e->getMessage(), Notice::log); + } else { + $this->error($e->getMessage(), Notice::logOnly); + } } } - $this->unlockForWriting(); + if($locked) $this->unlockForWriting(); return $numSaved; } @@ -741,18 +747,27 @@ abstract class FieldtypeMulti extends Fieldtype { * */ protected function lockForWriting(Field $field) { - $database = $this->wire('database'); + + $database = $this->wire()->database; $table = $database->escapeTable($field->getTable()); $locked = false; - try { - // attempt lock if possible - if($database->exec("LOCK TABLES `$table` WRITE") !== false) { - $this->lockedTable = true; - $locked = true; + $numAttempts = 0; + $maxAttempts = 100; + $lastException = null; + + do { + try { + // attempt lock if possible + if($database->exec("LOCK TABLES `$table` WRITE") !== false) { + $this->lockedTable = true; + $locked = true; + } + } catch(\Exception $e) { + $lastException = $e; } - } catch(\Exception $e) { - // ignore - } + } while(!$locked && $numAttempts++ < $maxAttempts); + + if(!$locked && $lastException) $this->trackException($lastException, false); return $locked; } @@ -766,11 +781,11 @@ abstract class FieldtypeMulti extends Fieldtype { protected function unlockForWriting() { $result = false; if($this->lockedTable) try { - $this->wire('database')->exec("UNLOCK TABLES"); + $this->wire()->database->exec("UNLOCK TABLES"); $this->lockedTable = false; $result = true; } catch(\Exception $e) { - // ignore + $this->trackException($e, false); } return $result; }