/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.capedwarf.admin; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.annotation.PostConstruct; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; import com.google.appengine.api.NamespaceManager; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.FetchOptions; import com.google.appengine.api.datastore.Query; import org.jboss.capedwarf.datastore.NamespaceServiceFactory; import org.jboss.capedwarf.datastore.NamespaceServiceInternal; import org.jboss.capedwarf.shared.compatibility.Compatibility; import static com.google.appengine.api.datastore.Query.FilterOperator.EQUAL; import static org.jboss.capedwarf.admin.NumberFormatter.formatBytes; import static org.jboss.capedwarf.admin.NumberFormatter.formatCount; /** * @author <a href="mailto:mluksa@redhat.com">Marko Luksa</a> */ @Named("datastoreStatistics") @RequestScoped @SuppressWarnings("UnusedDeclaration") public class DatastoreStatistics extends DatastoreHolder { public static final String ALL_NAMESPACES = "!"; @Inject @HttpParam private String selectedNamespace = ALL_NAMESPACES; @Inject @HttpParam private String selectedEntityKind; private Entity statEntity; @PostConstruct private void loadStatEntity() { if (!isEnabled()) { return; } if (getSelectedNamespace().equals(ALL_NAMESPACES)) { NamespaceManager.set(""); if (selectedEntityKind == null || selectedEntityKind.equals("")) { statEntity = getStatEntity("__Stat_Total__"); } else { statEntity = getStatEntity("__Stat_Kind__", selectedEntityKind); } } else { NamespaceManager.set(getSelectedNamespace()); try { if (selectedEntityKind == null || selectedEntityKind.equals("")) { statEntity = getStatEntity("__Stat_Ns_Total__"); } else { statEntity = getStatEntity("__Stat_Ns_Kind__", selectedEntityKind); } } finally { NamespaceManager.set(""); } } } private Entity getStatEntity(String statEntityKind, String entityKind) { Query query = new Query(statEntityKind) .setFilter(new Query.FilterPredicate("kind_name", EQUAL, entityKind)) .addSort("timestamp", Query.SortDirection.DESCENDING) ; List<Entity> list = getDatastore().prepare(query).asList(FetchOptions.Builder.withLimit(1)); return list.isEmpty() ? null : list.get(0); } private Entity getStatEntity(String kind) { Query query = new Query(kind) .addSort("timestamp", Query.SortDirection.DESCENDING); List<Entity> list = getDatastore().prepare(query).asList(FetchOptions.Builder.withLimit(1)); return list.isEmpty() ? null : list.get(0); } public Column getEntities() { if (statEntity == null) { loadStatEntity(); } if (statEntity == null) { return new Column(0, 0); } else { return new Column((Long) statEntity.getProperty("bytes"), (Long) statEntity.getProperty("count")); } } public Column getBuiltInIndexes() { return new Column(0, 0); } public Column getCompositeIndexes() { return new Column(0, 0); } public Column getTotal() { Column column = new Column(0, 0); column.add(getEntities()); column.add(getBuiltInIndexes()); column.add(getCompositeIndexes()); return column; } public String getSelectedEntityKind() { return selectedEntityKind; } public void setSelectedEntityKind(String selectedEntityKind) { this.selectedEntityKind = selectedEntityKind; } public String getSelectedNamespace() { return selectedNamespace == null ? ALL_NAMESPACES : selectedNamespace; } public void setSelectedNamespace(String selectedNamespace) { this.selectedNamespace = selectedNamespace; } public Set<String> getNamespaces() { NamespaceServiceInternal namespaceService = NamespaceServiceFactory.getNamespaceService(); return namespaceService.getNamespaces(); } public Set<String> getEntityKinds() { NamespaceServiceInternal namespaceService = NamespaceServiceFactory.getNamespaceService(); if (getSelectedNamespace().equals(ALL_NAMESPACES)) { Set<String> allKinds = new HashSet<String>(); for (String ns : namespaceService.getNamespaces()) { allKinds.addAll(namespaceService.getKindsPerNamespace(ns)); } return allKinds; } else { return namespaceService.getKindsPerNamespace(getSelectedNamespace()); } } public boolean isEnabled() { String stats = Compatibility.getInstance().getValue(Compatibility.Feature.ENABLE_EAGER_DATASTORE_STATS); return "sync".equals(stats) || "async".equals(stats); } public static class Column { private long bytes; private long count; public Column(long bytes, long count) { this.bytes = bytes; this.count = count; } public String getTotalSize() { return formatBytes(bytes); } public String getEntryCount() { return formatCount(count); } public String getAverageSize() { return count == 0 ? "" : formatBytes(bytes / count); } public void add(Column column) { bytes += column.bytes; count += column.count; } } }