|
6 | 6 | import java.lang.reflect.Array;
|
7 | 7 | import java.util.ArrayList;
|
8 | 8 | import java.util.List;
|
| 9 | +import java.util.concurrent.atomic.AtomicBoolean; |
9 | 10 | import java.util.function.Function;
|
10 | 11 |
|
11 | 12 | import javax.validation.constraints.NotNull;
|
12 | 13 |
|
13 | 14 | import org.apache.commons.lang3.StringUtils;
|
14 | 15 |
|
15 | 16 | import com.aerospike.client.AerospikeException;
|
| 17 | +import com.aerospike.client.AerospikeException.ScanTerminated; |
16 | 18 | import com.aerospike.client.Bin;
|
17 | 19 | import com.aerospike.client.IAerospikeClient;
|
18 | 20 | import com.aerospike.client.Key;
|
|
24 | 26 | import com.aerospike.client.policy.RecordExistsAction;
|
25 | 27 | import com.aerospike.client.policy.ScanPolicy;
|
26 | 28 | import com.aerospike.client.policy.WritePolicy;
|
| 29 | +import com.aerospike.client.query.Filter; |
27 | 30 | import com.aerospike.client.query.RecordSet;
|
28 | 31 | import com.aerospike.client.query.Statement;
|
29 | 32 | import com.aerospike.mapper.tools.ClassCache.PolicyType;
|
@@ -613,6 +616,153 @@ public <T> void find(@NotNull Class<T> clazz, Function<T, Boolean> function) thr
|
613 | 616 | }
|
614 | 617 | }
|
615 | 618 |
|
| 619 | + /** |
| 620 | + * Scan every record in the set associated with the passed class. Each record will be converted to the appropriate class then passed to the |
| 621 | + * processor. If the processor returns true, more records will be processed and if the processor returns false, the scan is aborted. |
| 622 | + * <p/> |
| 623 | + * Depending on the ScanPolicy set up for this class, it is possible for the processor to be called by multiple different |
| 624 | + * threads concurrently, so the processor should be thread-safe |
| 625 | + * |
| 626 | + * @param clazz - the class used to determine which set to scan and to convert the returned records to. |
| 627 | + * @param processor - the Processor used to process each record |
| 628 | + */ |
| 629 | + @Override |
| 630 | + public <T> void scan(@NotNull Class<T> clazz, @NotNull Processor<T> processor) { |
| 631 | + scan(null, clazz, processor); |
| 632 | + } |
| 633 | + |
| 634 | + /** |
| 635 | + * Scan every record in the set associated with the passed class. Each record will be converted to the appropriate class then passed to the |
| 636 | + * processor. If the processor returns true, more records will be processed and if the processor returns false, the scan is aborted. |
| 637 | + * <p/> |
| 638 | + * Depending on the policy passed or set as the ScanPolicy for this class, it is possible for the processor to be called by multiple different |
| 639 | + * threads concurrently, so the processor should be thread-safe. Note that as a consequence of this, if the processor returns false to abort the |
| 640 | + * scan there is a chance that records are being concurrently processed in other threads and this processing will not be interrupted. |
| 641 | + * <p/> |
| 642 | + * |
| 643 | + * @param policy - the scan policy to use. If this is null, the default scan policy of the passed class will be used. |
| 644 | + * @param clazz - the class used to determine which set to scan and to convert the returned records to. |
| 645 | + * @param processor - the Processor used to process each record |
| 646 | + */ |
| 647 | + @Override |
| 648 | + public <T> void scan(ScanPolicy policy, @NotNull Class<T> clazz, @NotNull Processor<T> processor) { |
| 649 | + scan(policy, clazz, processor, -1); |
| 650 | + } |
| 651 | + |
| 652 | + /** |
| 653 | + * Scan every record in the set associated with the passed class, limiting the throughput to the specified recordsPerSecond. Each record will be converted |
| 654 | + * to the appropriate class then passed to the |
| 655 | + * processor. If the processor returns true, more records will be processed and if the processor returns false, the scan is aborted. |
| 656 | + * <p/> |
| 657 | + * Depending on the ScanPolicy set up for this class, it is possible for the processor to be called by multiple different |
| 658 | + * threads concurrently, so the processor should be thread-safe |
| 659 | + * |
| 660 | + * @param clazz - the class used to determine which set to scan and to convert the returned records to. |
| 661 | + * @param processor - the Processor used to process each record |
| 662 | + * @param recordsPerSecond - the maximum number of records to be processed every second. |
| 663 | + */ |
| 664 | + @Override |
| 665 | + public <T> void scan(@NotNull Class<T> clazz, @NotNull Processor<T> processor, int recordsPerSecond) { |
| 666 | + scan(null, clazz, processor, recordsPerSecond); |
| 667 | + } |
| 668 | + |
| 669 | + /** |
| 670 | + * Scan every record in the set associated with the passed class. Each record will be converted to the appropriate class then passed to the |
| 671 | + * processor. If the processor returns true, more records will be processed and if the processor returns false, the scan is aborted. |
| 672 | + * <p/> |
| 673 | + * Depending on the policy passed or set as the ScanPolicy for this class, it is possible for the processor to be called by multiple different |
| 674 | + * threads concurrently, so the processor should be thread-safe. Note that as a consequence of this, if the processor returns false to abort the |
| 675 | + * scan there is a chance that records are being concurrently processed in other threads and this processing will not be interrupted. |
| 676 | + * <p/> |
| 677 | + * |
| 678 | + * @param policy - the scan policy to use. If this is null, the default scan policy of the passed class will be used. |
| 679 | + * @param clazz - the class used to determine which set to scan and to convert the returned records to. |
| 680 | + * @param processor - the Processor used to process each record |
| 681 | + * @param recordsPerSecond - the number of records to process per second. Set to 0 for unlimited, > 0 for a finite rate, < 0 for no change |
| 682 | + * (use the value from the passed policy) |
| 683 | + */ |
| 684 | + @Override |
| 685 | + public <T> void scan(ScanPolicy policy, @NotNull Class<T> clazz, @NotNull Processor<T> processor, int recordsPerSecond) { |
| 686 | + ClassCacheEntry<T> entry = MapperUtils.getEntryAndValidateNamespace(clazz, this); |
| 687 | + if (policy == null) { |
| 688 | + policy = entry.getScanPolicy(); |
| 689 | + } |
| 690 | + if (recordsPerSecond >= 0) { |
| 691 | + // Ensure the underlying rate on the policy does not change |
| 692 | + policy = new ScanPolicy(policy); |
| 693 | + policy.recordsPerSecond = recordsPerSecond; |
| 694 | + } |
| 695 | + String namespace = entry.getNamespace(); |
| 696 | + String setName = entry.getSetName(); |
| 697 | + |
| 698 | + AtomicBoolean userTerminated = new AtomicBoolean(false); |
| 699 | + try { |
| 700 | + mClient.scanAll(policy, namespace, setName, (key, record) -> { |
| 701 | + T object = this.getMappingConverter().convertToObject(clazz, record); |
| 702 | + if (!processor.process(object)) { |
| 703 | + userTerminated.set(true); |
| 704 | + throw new AerospikeException.ScanTerminated(); |
| 705 | + } |
| 706 | + }); |
| 707 | + } catch (ScanTerminated st) { |
| 708 | + if (!userTerminated.get()) { |
| 709 | + throw st; |
| 710 | + } |
| 711 | + } |
| 712 | + } |
| 713 | + |
| 714 | + /** |
| 715 | + * Perform a secondary index query with the specified query policy. Each record will be converted |
| 716 | + * to the appropriate class then passed to the processor. If the processor returns false the query is aborted |
| 717 | + * whereas if the processor returns true subsequent records (if any) are processed. |
| 718 | + * <p/> |
| 719 | + * The query policy used will be the one associated with the passed classtype. |
| 720 | + * |
| 721 | + * @param clazz - the class used to determine which set to scan and to convert the returned records to. |
| 722 | + * @param processor - the Processor used to process each record |
| 723 | + * @param filter - the filter used to determine which secondary index to use. If this filter is null, every record in the set |
| 724 | + * associated with the passed classtype will be scanned, effectively turning the query into a scan |
| 725 | + */ |
| 726 | + @Override |
| 727 | + public <T> void query(@NotNull Class<T> clazz, @NotNull Processor<T> processor, Filter filter) { |
| 728 | + query(null, clazz, processor, filter); |
| 729 | + } |
| 730 | + |
| 731 | + /** |
| 732 | + * Perform a secondary index query with the specified query policy. Each record will be converted |
| 733 | + * to the appropriate class then passed to the processor. If the processor returns false the query is aborted |
| 734 | + * whereas if the processor returns true subsequent records (if any) are processed. |
| 735 | + * |
| 736 | + * @param policy - The query policy to use. If this parameter is not passed, the query policy associated with the passed classtype will be used |
| 737 | + * @param clazz - the class used to determine which set to scan and to convert the returned records to. |
| 738 | + * @param processor - the Processor used to process each record |
| 739 | + * @param filter - the filter used to determine which secondary index to use. If this filter is null, every record in the set |
| 740 | + * associated with the passed classtype will be scanned, effectively turning the query into a scan |
| 741 | + */ |
| 742 | + @Override |
| 743 | + public <T> void query(QueryPolicy policy, @NotNull Class<T> clazz, @NotNull Processor<T> processor, Filter filter) { |
| 744 | + ClassCacheEntry<T> entry = MapperUtils.getEntryAndValidateNamespace(clazz, this); |
| 745 | + if (policy == null) { |
| 746 | + policy = entry.getQueryPolicy(); |
| 747 | + } |
| 748 | + Statement statement = new Statement(); |
| 749 | + statement.setFilter(filter); |
| 750 | + statement.setNamespace(entry.getNamespace()); |
| 751 | + statement.setSetName(entry.getSetName()); |
| 752 | + |
| 753 | + RecordSet recordSet = mClient.query(policy, statement); |
| 754 | + try { |
| 755 | + while (recordSet.next()) { |
| 756 | + T object = this.getMappingConverter().convertToObject(clazz, recordSet.getRecord()); |
| 757 | + if (!processor.process(object)) { |
| 758 | + break; |
| 759 | + } |
| 760 | + } |
| 761 | + } finally { |
| 762 | + recordSet.close(); |
| 763 | + } |
| 764 | + } |
| 765 | + |
616 | 766 | @Override
|
617 | 767 | public IAerospikeClient getClient() {
|
618 | 768 | return this.mClient;
|
|
0 commit comments