All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dell.doradus.logservice.search.Searcher Maven / Gradle / Ivy

The newest version!
package com.dell.doradus.logservice.search;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import com.dell.doradus.common.ApplicationDefinition;
import com.dell.doradus.common.FieldDefinition;
import com.dell.doradus.common.FieldType;
import com.dell.doradus.common.TableDefinition;
import com.dell.doradus.logservice.ChunkInfo;
import com.dell.doradus.logservice.ChunkReader;
import com.dell.doradus.logservice.LogAggregate;
import com.dell.doradus.logservice.LogEntry;
import com.dell.doradus.logservice.LogQuery;
import com.dell.doradus.logservice.LogService;
import com.dell.doradus.logservice.SyntheticFields;
import com.dell.doradus.logservice.search.filter.FilterBuilder;
import com.dell.doradus.logservice.search.filter.IFilter;
import com.dell.doradus.olap.aggregate.AggregationResult;
import com.dell.doradus.olap.io.BSTR;
import com.dell.doradus.olap.store.BitVector;
import com.dell.doradus.search.SearchResultList;
import com.dell.doradus.search.aggregate.AggregationGroup;
import com.dell.doradus.search.parser.DoradusQueryBuilder;
import com.dell.doradus.search.query.Query;
import com.dell.doradus.service.db.DBService;
import com.dell.doradus.service.db.DColumn;
import com.dell.doradus.service.db.Tenant;

public class Searcher {
    
    public static SearchResultList search(LogService ls, Tenant tenant, String application, String table, LogQuery logQuery) {
        SearchRequest request = new SearchRequest(tenant, application, table, logQuery);
        SearchCollector collector = new SearchCollector(request.getCount());
        LogEntry current = null;
        List partitions = ls.getPartitions(tenant, application, table, request.getMinTimestamp(), request.getMaxTimestamp());
        //optimization: inverse partitions
        if(request.getSkipCount() && request.getSortDescending()) {
            Collections.reverse(partitions);
        }
        IFilter filter = FilterBuilder.build(request.getQuery());
        ChunkReader chunkReader = new ChunkReader();
        if(logQuery.getPattern() != null) chunkReader.setSyntheticFields(logQuery.getPattern());
        
        int documentsCount = 0;
        for(String partition: partitions) {
            long minPartitionTimestamp = ls.getTimestamp(partition);
            long maxPartitionTimestamp = minPartitionTimestamp + 1000 * 3600 * 24;
            if(!checkInRange(minPartitionTimestamp, maxPartitionTimestamp, request, collector)) continue;
            Iterable chunks = ls.getChunks(tenant, application, table, partition);
            chunks = new SortedChunkIterable(chunks, request.getSortDescending());
            for(ChunkInfo chunkInfo: chunks) {
                if(!checkInRange(chunkInfo.getMinTimestamp(), chunkInfo.getMaxTimestamp(), request, collector)) continue;
                int c = filter.check(chunkInfo);
                if(c == -1) continue;
                BitVector bv = new BitVector(chunkInfo.getEventsCount());
                ls.readChunk(tenant, application, table, chunkInfo, chunkReader);
                if(c == 1) bv.setAll();
                else filter.check(chunkReader, bv);
                
                if(request.getSortDescending()) {
                    for(int i = chunkReader.size() - 1; i >= 0; i--) {
                        if(!bv.get(i)) continue;
                        long timestamp = chunkReader.getTimestamp(i);
                        if(timestamp < request.getMinTimestamp()) continue;
                        if(timestamp >= request.getMaxTimestamp()) continue;
                        //optimization: avoid instantiating LogEntry if it won't go to the results
                        if(collector.size() < request.getCount() || timestamp > collector.getMinTimestamp()) {
                            if(current == null) current = new LogEntry(request.getFields(), request.getSortDescending());
                            current.set(chunkReader, i);
                            current = collector.add(current);
                        }
                        documentsCount++;
                    }
                } else {
                    for(int i = 0; i < chunkReader.size(); i++) {
                        if(!bv.get(i)) continue;
                        long timestamp = chunkReader.getTimestamp(i);
                        if(timestamp < request.getMinTimestamp()) continue;
                        if(timestamp >= request.getMaxTimestamp()) continue;
                        //optimization: avoid instantiating LogEntry if it won't go to the results
                        if(collector.size() < request.getCount() || timestamp < collector.getMaxTimestamp()) {
                            if(current == null) current = new LogEntry(request.getFields(), request.getSortDescending());
                            current.set(chunkReader, i);
                            current = collector.add(current);
                        }
                        documentsCount++;
                    }
                }
            }
        }
        
        SearchResultList list = collector.getSearchResult(request.getFieldSet(), request.getSortOrders());
        if(!request.getSkipCount()) list.documentsCount = documentsCount;
        if(list.results.size() == request.getCount()) list.continuation_token = list.results.get(list.results.size() - 1).id();
        if(request.getSkip() > 0) {
            int size = list.results.size();
            if(request.getSkip() >= size) list.results.clear();
            else list.results = new ArrayList<>(list.results.subList(request.getSkip(), size));
        }
        return list;
    }
    
    private static boolean checkInRange(long minTimestamp, long maxTimestamp, SearchRequest request, SearchCollector collector) {
        if(maxTimestamp < request.getMinTimestamp()) return false;
        if(minTimestamp >= request.getMaxTimestamp()) return false;
        if(request.getSkipCount() && collector.size() >= request.getCount()) {
            if(request.getSortDescending()) {
                if(maxTimestamp <= collector.getMinTimestamp()) return false;
            } else {
                if(minTimestamp >= collector.getMaxTimestamp()) return false;
            }
        }
        return true;
    }
    
    
    public static AggregationResult aggregate(LogService ls, Tenant tenant, String application, String table, LogAggregate logAggregate) {
        TableDefinition tableDef = Searcher.getTableDef(tenant, application, table, logAggregate.getPattern());
        Query query = DoradusQueryBuilder.Build(logAggregate.getQuery(), tableDef);
        AggregationGroup group = Aggregate.getAggregationGroup(tableDef, logAggregate.getFields());
        String field = Aggregate.getAggregateField(group);
        IFilter filter = FilterBuilder.build(query);
        AggregateCollector collector = null;
        if(group != null && group.batchexFilters != null) {
            collector = new AggregateCollectorSets(filter, group.batchexFilters, group.batchexAliases);
        }
        else if(field == null) {
            collector = new AggregateCollectorNoField(filter);
        }
        else if("Timestamp".equals(field)) {
            collector = new AggregateCollectorTimestamp(filter, group.truncate, group.timeZone); 
        }
        else {
            collector = new AggregateCollectorField(filter, field);
        }
        collector.setContext(ls, tenant, application, table, logAggregate.getPattern());
        
        List partitions = ls.getPartitions(tenant, application, table);
        for(String partition: partitions) {
            for(ChunkInfo chunkInfo: ls.getChunks(tenant, application, table, partition)) {
                collector.addChunk(chunkInfo);
            }
        }
            
        AggregationResult result = collector.getResult();

        if(group != null) {
            Comparator comparer = AggregationGroupComparator.getComparator(group);
            Collections.sort(result.groups, comparer);
            if(group.selectionValue > 0 && group.selectionValue < result.groups.size()) {
                result.groups = new ArrayList<>(result.groups.subList(0, group.selectionValue));
            }
        }
        
        return result;
    }
    
    
    
    public static TableDefinition getTableDef(Tenant tenant, String application, String table, String pattern) {
        String store = application + "_" + table;
        ApplicationDefinition appDef = new ApplicationDefinition();
        appDef.setAppName(application);
        TableDefinition tableDef = new TableDefinition(appDef, table);
        appDef.addTable(tableDef);
        addField(tableDef, "Timestamp", FieldType.TIMESTAMP);
        Iterator it = DBService.instance().getAllColumns(tenant, store, "fields");
        if(it != null) {
            while(it.hasNext()) {
                String field = it.next().getName();
                addField(tableDef, field);
            }
        }
        
        if(pattern != null) {
            SyntheticFields synth = new SyntheticFields(pattern);
            addField(tableDef, synth.getBaseFieldName().toString());
            for(BSTR field: synth.getFieldNames()) {
                addField(tableDef, field.toString());
            }
        }
        return tableDef;
    }
    
    private static FieldDefinition addField(TableDefinition tableDef, String field) {
        return addField(tableDef, field, FieldType.TEXT);
    }
    
    private static FieldDefinition addField(TableDefinition tableDef, String field, FieldType type) {
        FieldDefinition fieldDef = tableDef.getFieldDef(field);
        if(fieldDef != null) return fieldDef;
        fieldDef = new FieldDefinition(tableDef);
        fieldDef.setType(type);
        fieldDef.setName(field);
        tableDef.addFieldDefinition(fieldDef);
        return fieldDef;
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy