@@ -205,14 +205,14 @@ Key CLASS::get_key(const Link& link) NOEXCEPT
205205}
206206
207207TEMPLATE
208- template < typename Element, if_equal<Element::size, Size>>
208+ ELEMENT_CONSTRAINT
209209inline bool CLASS::find (const Key& key, Element& element) const NOEXCEPT
210210{
211211 return !find_link (key, element).is_terminal ();
212212}
213213
214214TEMPLATE
215- template < typename Element, if_equal<Element::size, Size>>
215+ ELEMENT_CONSTRAINT
216216inline Link CLASS::find_link (const Key& key, Element& element) const NOEXCEPT
217217{
218218 // This override avoids duplicated memory_ptr construct in get(first()).
@@ -225,7 +225,7 @@ inline Link CLASS::find_link(const Key& key, Element& element) const NOEXCEPT
225225}
226226
227227TEMPLATE
228- template < typename Element, if_equal<Element::size, Size>>
228+ ELEMENT_CONSTRAINT
229229inline bool CLASS::get (const Link& link, Element& element) const NOEXCEPT
230230{
231231 // This override is the normal form.
@@ -234,7 +234,7 @@ inline bool CLASS::get(const Link& link, Element& element) const NOEXCEPT
234234
235235// static
236236TEMPLATE
237- template < typename Element, if_equal<Element::size, Size>>
237+ ELEMENT_CONSTRAINT
238238inline bool CLASS::get (const memory_ptr& ptr, const Link& link,
239239 Element& element) NOEXCEPT
240240{
@@ -243,7 +243,7 @@ inline bool CLASS::get(const memory_ptr& ptr, const Link& link,
243243
244244// static
245245TEMPLATE
246- template < typename Element, if_equal<Element::size, Size>>
246+ ELEMENT_CONSTRAINT
247247inline bool CLASS::get (const iterator& it, Element& element) NOEXCEPT
248248{
249249 // This override avoids deadlock when holding iterator to the same table.
@@ -252,16 +252,17 @@ inline bool CLASS::get(const iterator& it, Element& element) NOEXCEPT
252252
253253// static
254254TEMPLATE
255- template < typename Element, if_equal<Element::size, Size>>
255+ ELEMENT_CONSTRAINT
256256inline bool CLASS::get (const iterator& it, const Link& link,
257257 Element& element) NOEXCEPT
258258{
259259 // This override avoids deadlock when holding iterator to the same table.
260260 return read (it.get (), link, element);
261261}
262262
263+ // static
263264TEMPLATE
264- template < typename Element, if_equal<Element::size, Size>>
265+ ELEMENT_CONSTRAINT
265266bool CLASS::set (const memory_ptr& ptr, const Link& link, const Key& key,
266267 const Element& element) NOEXCEPT
267268{
@@ -296,15 +297,15 @@ bool CLASS::set(const memory_ptr& ptr, const Link& link, const Key& key,
296297}
297298
298299TEMPLATE
299- template < typename Element, if_equal<Element::size, Size>>
300+ ELEMENT_CONSTRAINT
300301bool CLASS::set (const Link& link, const Key& key,
301302 const Element& element) NOEXCEPT
302303{
303304 return set (get_memory (), link, key, element);
304305}
305306
306307TEMPLATE
307- template < typename Element, if_equal<Element::size, Size>>
308+ ELEMENT_CONSTRAINT
308309inline Link CLASS::set_link (const Key& key, const Element& element) NOEXCEPT
309310{
310311 Link link{};
@@ -315,7 +316,7 @@ inline Link CLASS::set_link(const Key& key, const Element& element) NOEXCEPT
315316}
316317
317318TEMPLATE
318- template < typename Element, if_equal<Element::size, Size>>
319+ ELEMENT_CONSTRAINT
319320inline bool CLASS::set_link (Link& link, const Key& key,
320321 const Element& element) NOEXCEPT
321322{
@@ -324,7 +325,7 @@ inline bool CLASS::set_link(Link& link, const Key& key,
324325}
325326
326327TEMPLATE
327- template < typename Element, if_equal<Element::size, Size>>
328+ ELEMENT_CONSTRAINT
328329inline Link CLASS::put_link (const Key& key, const Element& element) NOEXCEPT
329330{
330331 Link link{};
@@ -335,7 +336,7 @@ inline Link CLASS::put_link(const Key& key, const Element& element) NOEXCEPT
335336}
336337
337338TEMPLATE
338- template < typename Element, if_equal<Element::size, Size>>
339+ ELEMENT_CONSTRAINT
339340inline bool CLASS::put_link (Link& link, const Key& key,
340341 const Element& element) NOEXCEPT
341342{
@@ -344,14 +345,14 @@ inline bool CLASS::put_link(Link& link, const Key& key,
344345}
345346
346347TEMPLATE
347- template < typename Element, if_equal<Element::size, Size>>
348+ ELEMENT_CONSTRAINT
348349inline bool CLASS::put (const Key& key, const Element& element) NOEXCEPT
349350{
350351 return !put_link (key, element).is_terminal ();
351352}
352353
353354TEMPLATE
354- template < typename Element, if_equal<Element::size, Size>>
355+ ELEMENT_CONSTRAINT
355356inline bool CLASS::put (const Link& link, const Key& key,
356357 const Element& element) NOEXCEPT
357358{
@@ -360,53 +361,63 @@ inline bool CLASS::put(const Link& link, const Key& key,
360361}
361362
362363TEMPLATE
363- template < typename Element, if_equal<Element::size, Size>>
364+ ELEMENT_CONSTRAINT
364365inline bool CLASS::put (const memory_ptr& ptr, const Link& link, const Key& key,
365366 const Element& element) NOEXCEPT
366367{
367368 return write (ptr, link, key, element);
368369}
369370
370371TEMPLATE
371- bool CLASS::commit (const memory_ptr& ptr, const Link& link,
372- const Key& key) NOEXCEPT
372+ ELEMENT_CONSTRAINT
373+ inline bool CLASS::put (bool & duplicate, const memory_ptr& ptr,
374+ const Link& link, const Key& key, const Element& element) NOEXCEPT
373375{
374- using namespace system ;
375- if (!ptr)
376+ Link previous_head{} ;
377+ if (!write (previous_head, ptr, link, key, element) )
376378 return false ;
377379
378- // get element offset (fault)
379- const auto offset = ptr->offset (body::link_to_position (link));
380- if (is_null (offset))
381- return false ;
380+ duplicate = !first (ptr, previous_head, key).is_terminal ();
381+ return true ;
382+ }
382383
383- // // Set element search key.
384- // unsafe_array_cast<uint8_t, key_size>(std::next(offset,
385- // Link::size)) = key;
384+ TEMPLATE
385+ inline Link CLASS::commit_link (const Link& link, const Key& key) NOEXCEPT
386+ {
387+ if (!commit (link, key))
388+ return {};
386389
387- // Commit element to search index (terminal is a valid bucket index).
388- auto & next = unsafe_array_cast<uint8_t , Link::size>(offset);
389- return head_.push (link, next, head_.index (key));
390+ return link;
390391}
391392
392393TEMPLATE
393- bool CLASS::commit (const Link& link, const Key& key) NOEXCEPT
394+ inline bool CLASS::commit (const Link& link, const Key& key) NOEXCEPT
394395{
395396 return commit (get_memory (), link, key);
396397}
397398
398399TEMPLATE
399- inline Link CLASS::commit_link (const Link& link, const Key& key) NOEXCEPT
400+ bool CLASS::commit (const memory_ptr& ptr, const Link& link,
401+ const Key& key) NOEXCEPT
400402{
401- if (!commit (link, key))
402- return {};
403+ using namespace system ;
404+ if (!ptr)
405+ return false ;
403406
404- return link;
407+ // get element offset (fault)
408+ const auto offset = ptr->offset (body::link_to_position (link));
409+ if (is_null (offset))
410+ return false ;
411+
412+ // Commit element to search index (terminal is a valid bucket index).
413+ auto & next = unsafe_array_cast<uint8_t , Link::size>(offset);
414+ return head_.push (link, next, head_.index (key));
405415}
406416
407- // protected/static
417+ // protected
408418// ----------------------------------------------------------------------------
409419
420+ // static
410421TEMPLATE
411422Link CLASS::first (const memory_ptr& ptr, const Link& link,
412423 const Key& key) NOEXCEPT
@@ -435,8 +446,9 @@ Link CLASS::first(const memory_ptr& ptr, const Link& link,
435446 return next;
436447}
437448
449+ // static
438450TEMPLATE
439- template < typename Element, if_equal<Element::size, Size>>
451+ ELEMENT_CONSTRAINT
440452bool CLASS::read (const memory_ptr& ptr, const Link& link,
441453 Element& element) NOEXCEPT
442454{
@@ -462,12 +474,12 @@ bool CLASS::read(const memory_ptr& ptr, const Link& link,
462474 reader source{ stream };
463475 source.skip_bytes (index_size);
464476
465- if constexpr (!is_slab) { BC_DEBUG_ONLY (source.set_limit (Size * element.count ());) }
477+ if constexpr (!is_slab) { BC_DEBUG_ONLY (source.set_limit (RowSize * element.count ());) }
466478 return element.from_data (source);
467479}
468480
469481TEMPLATE
470- template < typename Element, if_equal<Element::size, Size>>
482+ ELEMENT_CONSTRAINT
471483bool CLASS::write (const memory_ptr& ptr, const Link& link, const Key& key,
472484 const Element& element) NOEXCEPT
473485{
@@ -500,6 +512,50 @@ bool CLASS::write(const memory_ptr& ptr, const Link& link, const Key& key,
500512 return element.to_data (sink) && head_.push (link, next, head_.index (key));
501513}
502514
515+ TEMPLATE
516+ ELEMENT_CONSTRAINT
517+ bool CLASS::write (Link& previous, const memory_ptr& ptr, const Link& link,
518+ const Key& key, const Element& element) NOEXCEPT
519+ {
520+ using namespace system ;
521+ if (!ptr || link.is_terminal ())
522+ return false ;
523+
524+ const auto start = body::link_to_position (link);
525+ if (is_limited<ptrdiff_t >(start))
526+ return false ;
527+
528+ const auto size = ptr->size ();
529+ const auto position = possible_narrow_and_sign_cast<ptrdiff_t >(start);
530+ if (position > size)
531+ return false ;
532+
533+ const auto offset = ptr->offset (start);
534+ if (is_null (offset))
535+ return false ;
536+
537+ // iostream.flush is a nop (direct copy).
538+ iostream stream{ offset, size - position };
539+ finalizer sink{ stream };
540+ sink.skip_bytes (Link::size);
541+ keys::write (sink, key);
542+
543+ // Commit element to body.
544+ if constexpr (!is_slab) { BC_DEBUG_ONLY (sink.set_limit (RowSize * element.count ());) }
545+ auto & next = unsafe_array_cast<uint8_t , Link::size>(offset);
546+ if (!element.to_data (sink))
547+ return false ;
548+
549+ // Commit element to search (terminal is a valid bucket index).
550+ bool collision{};
551+ if (!head_.push (collision, link, next, head_.index (key)))
552+ return false ;
553+
554+ // If filter collision set previous stack head for conflict resolution.
555+ previous = collision ? next : Link::terminal;
556+ return true ;
557+ }
558+
503559} // namespace database
504560} // namespace libbitcoin
505561
0 commit comments