@@ -252,58 +252,104 @@ static void ets_delete_all_tables(struct Ets *ets, GlobalContext *global)
252
252
ets_delete_tables_internal (ets , true_pred , NULL , global );
253
253
}
254
254
255
- EtsErrorCode ets_insert ( term ref , term entry , Context * ctx )
255
+ static EtsErrorCode ets_table_insert ( struct EtsTable * ets_table , term entry , Context * ctx )
256
256
{
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
-
262
257
if (ets_table -> access_type != EtsAccessPublic && ets_table -> owner_process_id != ctx -> process_id ) {
263
- SMP_UNLOCK (ets_table );
264
258
return EtsPermissionDenied ;
265
259
}
266
260
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 ) {
269
264
return EtsBadEntry ;
270
265
}
271
266
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 )) {
275
269
return EtsAllocationFailure ;
276
270
}
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 )) {
281
274
return EtsAllocationFailure ;
282
275
}
283
276
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
+ }
286
279
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 ;
291
284
}
292
285
293
- SMP_UNLOCK (ets_table );
286
+ term iter = list ;
287
+ size_t size = 0 ;
294
288
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 ;
296
327
}
297
328
298
- EtsErrorCode ets_lookup (term ref , term key , term * ret , Context * ctx )
329
+ EtsErrorCode ets_insert (term name_or_ref , term entry , Context * ctx )
299
330
{
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 );
301
332
if (ets_table == NULL ) {
302
333
return EtsTableNotFound ;
303
334
}
304
335
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
+ {
305
352
if (ets_table -> access_type == EtsAccessPrivate && ets_table -> owner_process_id != ctx -> process_id ) {
306
- SMP_UNLOCK (ets_table );
307
353
return EtsPermissionDenied ;
308
354
}
309
355
@@ -316,24 +362,35 @@ EtsErrorCode ets_lookup(term ref, term key, term *ret, Context *ctx)
316
362
size_t size = (size_t ) memory_estimate_usage (res );
317
363
// allocate [object]
318
364
if (UNLIKELY (memory_ensure_free_opt (ctx , size + CONS_SIZE , MEMORY_CAN_SHRINK ) != MEMORY_GC_OK )) {
319
- SMP_UNLOCK (ets_table );
320
365
return EtsAllocationFailure ;
321
366
}
322
367
term new_res = memory_copy_term_tree (& ctx -> heap , res );
323
368
* ret = term_list_prepend (new_res , term_nil (), & ctx -> heap );
324
369
}
325
- SMP_UNLOCK (ets_table );
326
370
327
371
return EtsOk ;
328
372
}
329
373
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 )
331
388
{
332
389
if (UNLIKELY (pos == 0 )) {
333
390
return EtsBadPosition ;
334
391
}
335
392
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 );
337
394
if (ets_table == NULL ) {
338
395
return EtsTableNotFound ;
339
396
}
@@ -368,9 +425,9 @@ EtsErrorCode ets_lookup_element(term ref, term key, size_t pos, term *ret, Conte
368
425
return EtsOk ;
369
426
}
370
427
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 )
372
429
{
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 );
374
431
if (ets_table == NULL ) {
375
432
return EtsTableNotFound ;
376
433
}
0 commit comments