@@ -252,58 +252,104 @@ static void ets_delete_all_tables(struct Ets *ets, GlobalContext *global)
252252 ets_delete_tables_internal (ets , true_pred , NULL , global );
253253}
254254
255- EtsErrorCode ets_insert ( term ref , term entry , Context * ctx )
255+ static EtsErrorCode ets_table_insert ( struct EtsTable * ets_table , term entry , Context * ctx )
256256{
257- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessWrite ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessWrite );
258- if (ets_table == NULL ) {
259- return EtsTableNotFound ;
260- }
261-
262257 if (ets_table -> access_type != EtsAccessPublic && ets_table -> owner_process_id != ctx -> process_id ) {
263- SMP_UNLOCK (ets_table );
264258 return EtsPermissionDenied ;
265259 }
266260
267- if ((size_t ) term_get_tuple_arity (entry ) < (ets_table -> keypos + 1 )) {
268- SMP_UNLOCK (ets_table );
261+ size_t keypos = ets_table -> keypos ;
262+
263+ if ((size_t ) term_get_tuple_arity (entry ) < keypos + 1 ) {
269264 return EtsBadEntry ;
270265 }
271266
272- Heap * heap = malloc (sizeof (Heap ));
273- if (IS_NULL_PTR (heap )) {
274- SMP_UNLOCK (ets_table );
267+ struct HNode * new_node = ets_hashtable_new_node (entry , keypos );
268+ if (IS_NULL_PTR (new_node )) {
275269 return EtsAllocationFailure ;
276270 }
277- size_t size = (size_t ) memory_estimate_usage (entry );
278- if (memory_init_heap (heap , size ) != MEMORY_GC_OK ) {
279- free (heap );
280- SMP_UNLOCK (ets_table );
271+
272+ EtsHashtableErrorCode res = ets_hashtable_insert (ets_table -> hashtable , new_node , EtsHashtableAllowOverwrite , ctx -> global );
273+ if (UNLIKELY (res != EtsHashtableOk )) {
281274 return EtsAllocationFailure ;
282275 }
283276
284- term new_entry = memory_copy_term_tree ( heap , entry ) ;
285- term key = term_get_tuple_element ( new_entry , ( int ) ets_table -> keypos );
277+ return EtsOk ;
278+ }
286279
287- EtsErrorCode ret = EtsOk ;
288- EtsHashtableErrorCode res = ets_hashtable_insert ( ets_table -> hashtable , key , new_entry , EtsHashtableAllowOverwrite , heap , ctx -> global );
289- if (UNLIKELY ( res != EtsHashtableOk ) ) {
290- ret = EtsAllocationFailure ;
280+ static EtsErrorCode ets_table_insert_list ( struct EtsTable * ets_table , term list , Context * ctx )
281+ {
282+ if (ets_table -> access_type != EtsAccessPublic && ets_table -> owner_process_id != ctx -> process_id ) {
283+ return EtsPermissionDenied ;
291284 }
292285
293- SMP_UNLOCK (ets_table );
286+ term iter = list ;
287+ size_t size = 0 ;
294288
295- return ret ;
289+ while (term_is_nonempty_list (iter )) {
290+ term tuple = term_get_list_head (iter );
291+ iter = term_get_list_tail (iter );
292+ if (!term_is_tuple (tuple ) || (size_t ) term_get_tuple_arity (tuple ) < (ets_table -> keypos + 1 )) {
293+ return EtsBadEntry ;
294+ }
295+ ++ size ;
296+ }
297+ if (!term_is_nil (iter )) {
298+ return EtsBadEntry ;
299+ }
300+
301+ struct HNode * * nodes = malloc (size * sizeof (struct HNode * ));
302+ if (IS_NULL_PTR (nodes )) {
303+ return EtsAllocationFailure ;
304+ }
305+
306+ size_t i = 0 ;
307+ while (term_is_nonempty_list (list )) {
308+ term tuple = term_get_list_head (list );
309+ nodes [i ] = ets_hashtable_new_node (tuple , ets_table -> keypos );
310+ if (IS_NULL_PTR (nodes [i ])) {
311+ ets_hashtable_free_node_array (nodes , i , ctx -> global );
312+ free (nodes );
313+ return EtsAllocationFailure ;
314+ }
315+ ++ i ;
316+ list = term_get_list_tail (list );
317+ }
318+
319+ for (size_t i = 0 ; i < size ; ++ i ) {
320+
321+ EtsHashtableErrorCode res = ets_hashtable_insert (ets_table -> hashtable , nodes [i ], EtsHashtableAllowOverwrite , ctx -> global );
322+ assert (res == EtsHashtableOk );
323+ }
324+
325+ free (nodes );
326+ return EtsOk ;
296327}
297328
298- EtsErrorCode ets_lookup (term ref , term key , term * ret , Context * ctx )
329+ EtsErrorCode ets_insert (term name_or_ref , term entry , Context * ctx )
299330{
300- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessRead );
331+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessWrite ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessWrite );
301332 if (ets_table == NULL ) {
302333 return EtsTableNotFound ;
303334 }
304335
336+ EtsErrorCode result ;
337+ if (term_is_tuple (entry )) {
338+ result = ets_table_insert (ets_table , entry , ctx );
339+ } else if (term_is_list (entry )) {
340+ result = ets_table_insert_list (ets_table , entry , ctx );
341+ } else {
342+ result = EtsBadEntry ;
343+ }
344+
345+ SMP_UNLOCK (ets_table );
346+
347+ return result ;
348+ }
349+
350+ static EtsErrorCode ets_table_lookup (struct EtsTable * ets_table , term key , term * ret , Context * ctx )
351+ {
305352 if (ets_table -> access_type == EtsAccessPrivate && ets_table -> owner_process_id != ctx -> process_id ) {
306- SMP_UNLOCK (ets_table );
307353 return EtsPermissionDenied ;
308354 }
309355
@@ -316,24 +362,35 @@ EtsErrorCode ets_lookup(term ref, term key, term *ret, Context *ctx)
316362 size_t size = (size_t ) memory_estimate_usage (res );
317363 // allocate [object]
318364 if (UNLIKELY (memory_ensure_free_opt (ctx , size + CONS_SIZE , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
319- SMP_UNLOCK (ets_table );
320365 return EtsAllocationFailure ;
321366 }
322367 term new_res = memory_copy_term_tree (& ctx -> heap , res );
323368 * ret = term_list_prepend (new_res , term_nil (), & ctx -> heap );
324369 }
325- SMP_UNLOCK (ets_table );
326370
327371 return EtsOk ;
328372}
329373
330- EtsErrorCode ets_lookup_element (term ref , term key , size_t pos , term * ret , Context * ctx )
374+ EtsErrorCode ets_lookup (term name_or_ref , term key , term * ret , Context * ctx )
375+ {
376+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessRead );
377+ if (ets_table == NULL ) {
378+ return EtsTableNotFound ;
379+ }
380+
381+ EtsErrorCode result = ets_table_lookup (ets_table , key , ret , ctx );
382+ SMP_UNLOCK (ets_table );
383+
384+ return result ;
385+ }
386+
387+ EtsErrorCode ets_lookup_element (term name_or_ref , term key , size_t pos , term * ret , Context * ctx )
331388{
332389 if (UNLIKELY (pos == 0 )) {
333390 return EtsBadPosition ;
334391 }
335392
336- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessRead );
393+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessRead );
337394 if (ets_table == NULL ) {
338395 return EtsTableNotFound ;
339396 }
@@ -368,9 +425,9 @@ EtsErrorCode ets_lookup_element(term ref, term key, size_t pos, term *ret, Conte
368425 return EtsOk ;
369426}
370427
371- EtsErrorCode ets_delete (term ref , term key , term * ret , Context * ctx )
428+ EtsErrorCode ets_delete (term name_or_ref , term key , term * ret , Context * ctx )
372429{
373- struct EtsTable * ets_table = term_is_atom (ref ) ? ets_get_table_by_name (& ctx -> global -> ets , ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (ref ), TableAccessRead );
430+ struct EtsTable * ets_table = term_is_atom (name_or_ref ) ? ets_get_table_by_name (& ctx -> global -> ets , name_or_ref , TableAccessRead ) : ets_get_table_by_ref (& ctx -> global -> ets , term_to_ref_ticks (name_or_ref ), TableAccessRead );
374431 if (ets_table == NULL ) {
375432 return EtsTableNotFound ;
376433 }
0 commit comments