diff --git a/README.md b/README.md index 6f6e730d..51683ed0 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,8 @@ The fastest way to experience the Coherence CLI is to follow the The CLI supports and is certified against the following Community and Commercial editions of Coherence: **Coherence Community Edition** -* 23.03 -* 22.06.x +* 23.09.+ +* 22.06.+ * 14.1.1-0-12+ **Coherence Grid/ Enterprise Edition** diff --git a/docs/reference/25_caches.adoc b/docs/reference/25_caches.adoc index 9719784b..e92b8d09 100644 --- a/docs/reference/25_caches.adoc +++ b/docs/reference/25_caches.adoc @@ -15,7 +15,10 @@ There are various commands that allow you to work with and manage cluster caches * <> - displays the caches for a cluster * <> - shows information related to a specific cache and service -* <> - displays the cache stores for a cache and service +* <> - displays cache stores for a cache and service +* <> - displays cache storage information for a cache and service +* <> - displays cache access information for a cache and service +* <> - displays cache index information for a cache and service * <> - sets an attribute for a cache across one or more members * <> - truncates a caches contents, not generating any cache events * <> - clears a caches contents @@ -206,22 +209,72 @@ You may omit the service name if the cache name is unique. NOTE: If you do not use the `-o wide` option, then you will only see service, cache name, count and size. -Display all caches for a particular service. +[#get-cache-storage] +==== Get Cache Storage + +include::../../build/_output/docs-gen/get_cache_storage.adoc[tag=text] [source,bash] ---- -cohctl get caches -c local -s PartitionedCache -o wide -m +cohctl get cache-storage -c local test ---- Output: [source,bash] ---- -Total Caches: 2, Total primary storage: 36 MB -SERVICE CACHE COUNT SIZE AVG SIZE TOTAL PUTS TOTAL GETS TOTAL REMOVES TOTAL HITS TOTAL MISSES HIT PROB -PartitionedCache customers 100,000 25 MB 262 200,000 0 0 0 0 0.00% -PartitionedCache orders 10,000 11 MB 1,160 20,000 20,000 0 20,000 0 100.00% +Cache: test + +NODE ID TIER LOCKS GRANTED LOCKS PENDING KEY LISTENERS FILTER LISTENERS MAX QUERY MS MAX QUERY DESC + 1 back 0 0 0 0 0 + 2 back 0 0 0 0 0 + 3 back 0 0 0 0 0 ---- +[#get-cache-access] +==== Get Cache Access + +include::../../build/_output/docs-gen/get_cache_access.adoc[tag=text] + +[source,bash] +---- +cohctl get cache-access -c local test +---- +Output: +[source,bash] +---- +Cache: test + +NODE ID TIER COUNT SIZE PUTS GETS REMOVES CLEARS EVICTIONS + 1 back 0 0 MB 0 0 0 2 0 + 2 back 0 0 MB 2 0 2 2 0 + 3 back 0 0 MB 0 0 0 2 0 +---- + +[#get-cache-indexes] +==== Get Cache Indexes + +include::../../build/_output/docs-gen/get_cache_indexes.adoc[tag=text] + +[source,bash] +---- +cohctl get cache-indexes -c local test +---- +Output: +[source,bash] +---- +Cache: test + +Total Indexing Bytes: 49,756 +Total Indexing: 0 MB +Total Indexing Millis: 1,942 + +Node:2: PartitionedIndex: Extractor=.toString()(), Ordered=true, Footprint=16.2KB +Node:1: PartitionedIndex: Extractor=.toString()(), Ordered=true, Footprint=16.2KB +Node:3: PartitionedIndex: Extractor=.toString()(), Ordered=true, Footprint=16.0KB +---- + +NOTE: Depending upon the Coherence version, you may not see all the above information. + [#set-cache] ==== Set Cache diff --git a/pkg/cmd/cache.go b/pkg/cmd/cache.go index 059867d1..98143436 100644 --- a/pkg/cmd/cache.go +++ b/pkg/cmd/cache.go @@ -343,6 +343,140 @@ You can specify '-o wide' to display addition information.`, }, } +// getCacheAccessCmd represents the get cache-access command. +var getCacheAccessCmd = &cobra.Command{ + Use: "cache-access cache-name", + Short: "display cache access information for a cache and service", + Long: `The 'get cache-access' command displays cache access information related to a specific cache. +You can specify '-o wide' to display addition information.`, + ValidArgsFunction: completionCaches, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + displayErrorAndExit(cmd, provideCacheMessage) + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + return getCacheDetails(cmd, args, "access") + }, +} + +// getCacheStorageCmd represents the get cache-storage command. +var getCacheStorageCmd = &cobra.Command{ + Use: "cache-storage cache-name", + Short: "display cache storage information for a cache and service", + Long: `The 'get cache-storage' command displays cache storage information related to a specific cache. +You can specify '-o wide' to display addition information.`, + ValidArgsFunction: completionCaches, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + displayErrorAndExit(cmd, provideCacheMessage) + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + return getCacheDetails(cmd, args, "storage") + }, +} + +// getCacheIndexesCmd represents the get cache-indexes command. +var getCacheIndexesCmd = &cobra.Command{ + Use: "cache-indexes cache-name", + Short: "display cache index information for a cache and service", + Long: `The 'get cache-indexes' command displays cache index information related to a specific cache.`, + ValidArgsFunction: completionCaches, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + displayErrorAndExit(cmd, provideCacheMessage) + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + return getCacheDetails(cmd, args, "index") + }, +} + +// getCacheDetails displays either access, storage or index details for a cache depending upon +// the value of displayType. +func getCacheDetails(cmd *cobra.Command, args []string, displayType string) error { + var ( + err error + dataFetcher fetcher.Fetcher + found bool + connection string + ) + + cacheName := args[0] + + connection, dataFetcher, err = GetConnectionAndDataFetcher() + if err != nil { + return err + } + + if serviceName, err = findServiceForCacheOrTopic(dataFetcher, cacheName, "cache"); err != nil { + return err + } + + found, err = ServiceExists(dataFetcher, serviceName) + if !found || err != nil { + return fmt.Errorf(cannotFindService, serviceName) + } + + for { + var ( + cacheResult []byte + cacheDetails = config.CacheDetails{} + result string + ) + + cacheResult, err = dataFetcher.GetCacheMembers(serviceName, cacheName) + if err != nil { + return err + } + + if string(cacheResult) == "{}" || len(cacheResult) == 0 { + return fmt.Errorf(cannotFindCache, cacheName, serviceName) + } + + if strings.Contains(OutputFormat, constants.JSONPATH) { + result, err = utils.GetJSONPathResults(cacheResult, OutputFormat) + if err != nil { + return err + } + cmd.Println(result) + } else if OutputFormat == constants.JSON { + cmd.Println(string(cacheResult)) + } else { + err = json.Unmarshal(cacheResult, &cacheDetails) + if err != nil { + return utils.GetError("unable to unmarshall cache result", err) + } + + printWatchHeader(cmd) + cmd.Println(FormatCurrentCluster(connection)) + + cmd.Printf("Cache: %s\n\n", args[0]) + + if displayType == "access" { + cmd.Println(FormatCacheDetailsSizeAndAccess(cacheDetails.Details)) + } else if displayType == "index" { + cmd.Println(FormatCacheIndexDetails(cacheDetails.Details)) + } else if displayType == "storage" { + cmd.Println(FormatCacheDetailsStorage(cacheDetails.Details)) + } + } + + // check to see if we should exit if we are not watching + if !isWatchEnabled() { + break + } + // we are watching so sleep and then repeat until CTRL-C + time.Sleep(time.Duration(watchDelay) * time.Second) + } + + return nil +} + // clearCacheCmd represents the clear cache command. var clearCacheCmd = &cobra.Command{ Use: "cache cache-name", @@ -720,6 +854,9 @@ func init() { describeCacheCmd.Flags().StringVarP(&serviceName, serviceNameOption, serviceNameOptionShort, "", serviceNameDescription) getCacheStoresCmd.Flags().StringVarP(&serviceName, serviceNameOption, serviceNameOptionShort, "", serviceNameDescription) + getCacheAccessCmd.Flags().StringVarP(&serviceName, serviceNameOption, serviceNameOptionShort, "", serviceNameDescription) + getCacheStorageCmd.Flags().StringVarP(&serviceName, serviceNameOption, serviceNameOptionShort, "", serviceNameDescription) + getCacheIndexesCmd.Flags().StringVarP(&serviceName, serviceNameOption, serviceNameOptionShort, "", serviceNameDescription) clearCacheCmd.Flags().StringVarP(&serviceName, serviceNameOption, serviceNameOptionShort, "", serviceNameDescription) clearCacheCmd.Flags().BoolVarP(&automaticallyConfirm, "yes", "y", false, confirmOptionMessage) diff --git a/pkg/cmd/formatting.go b/pkg/cmd/formatting.go index f85acb82..ca9cf4eb 100644 --- a/pkg/cmd/formatting.go +++ b/pkg/cmd/formatting.go @@ -816,13 +816,13 @@ func FormatCacheDetailsSizeAndAccess(cacheDetails []config.CacheDetail) string { }) table := newFormattedTable().WithHeader(NodeIDColumn, "TIER", "COUNT", "SIZE", - "PUTS", "GETS", "REMOVES", "EVICTIONS") + "PUTS", "GETS", "REMOVES", "CLEARS", "EVICTIONS") if OutputFormat == constants.WIDE { - table.WithAlignment(R, L, R, R, R, R, R, R, R, R, R, R, R, R) + table.WithAlignment(R, L, R, R, R, R, R, R, R, R, R, R, R, R, R) table.AddHeaderColumns("HITS", "MISSES", "HIT PROB", "STORE READS", "WRITES", "FAILURES") } else { - table.WithAlignment(R, L, R, R, R, R, R, R) + table.WithAlignment(R, L, R, R, R, R, R, R, R) } for _, value := range cacheDetails { @@ -841,7 +841,7 @@ func FormatCacheDetailsSizeAndAccess(cacheDetails []config.CacheDetail) string { formatSmallInteger(value.CacheSize), formattingFunction(unitsBytes), formatLargeInteger(value.TotalPuts), formatLargeInteger(totalGets), formatLargeInteger(value.TotalRemoves), - formatLargeInteger(value.Evictions)) + formatLargeInteger(value.TotalClears), formatLargeInteger(value.Evictions)) if OutputFormat == constants.WIDE { table.AddColumnsToRow(formatLargeInteger(totalHits), formatLargeInteger(value.CacheMisses), formatPercent(hitProb), diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index 6710a16f..7126a7b9 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -502,6 +502,9 @@ func Initialize(command *cobra.Command) *cobra.Command { getCmd.AddCommand(getServiceDescriptionCmd) getCmd.AddCommand(getClusterDescription) getCmd.AddCommand(getMemberDescriptionCmd) + getCmd.AddCommand(getCacheAccessCmd) + getCmd.AddCommand(getCacheStorageCmd) + getCmd.AddCommand(getCacheIndexesCmd) // set command command.AddCommand(setCmd) diff --git a/pkg/cmd/service.go b/pkg/cmd/service.go index 91c410e3..6f8da11b 100644 --- a/pkg/cmd/service.go +++ b/pkg/cmd/service.go @@ -523,7 +523,7 @@ var getServiceMembersCmd = &cobra.Command{ finalDetails = membersDetails.Services } - cmd.Println("Service: " + serviceName) + cmd.Println("Service: " + serviceName + "\n") cmd.Println(FormatServiceMembers(finalDetails)) } diff --git a/pkg/config/config_helper.go b/pkg/config/config_helper.go index b43f8eeb..cca06f3c 100644 --- a/pkg/config/config_helper.go +++ b/pkg/config/config_helper.go @@ -537,6 +537,7 @@ type CacheDetail struct { TotalPuts int64 `json:"totalPuts"` TotalGets int64 `json:"totalGets"` TotalRemoves int64 `json:"removeCount"` + TotalClears int64 `json:"clearCount"` CacheHits int64 `json:"cacheHits"` CacheMisses int64 `json:"cacheMisses"` Evictions int64 `json:"evictionCount"` diff --git a/scripts/generate-doc-snippets.sh b/scripts/generate-doc-snippets.sh index 8c18a983..65ebe979 100755 --- a/scripts/generate-doc-snippets.sh +++ b/scripts/generate-doc-snippets.sh @@ -108,6 +108,9 @@ create_doc $DOCS_DIR/set_management "${COHCTL} set management --help" # Caches create_doc $DOCS_DIR/get_caches "${COHCTL} get caches --help" create_doc $DOCS_DIR/get_cache_stores "${COHCTL} get cache-stores --help" +create_doc $DOCS_DIR/get_cache_storage "${COHCTL} get cache-storage --help" +create_doc $DOCS_DIR/get_cache_access "${COHCTL} get cache-access --help" +create_doc $DOCS_DIR/get_cache_indexes "${COHCTL} get cache-indexes --help" create_doc $DOCS_DIR/describe_cache "${COHCTL} describe cache --help" create_doc $DOCS_DIR/set_cache "${COHCTL} set cache --help" create_doc $DOCS_DIR/truncate_cache "${COHCTL} truncate cache --help" diff --git a/test/common/common.go b/test/common/common.go index 03ee1fc5..206bc547 100644 --- a/test/common/common.go +++ b/test/common/common.go @@ -1131,6 +1131,18 @@ func RunTestCachesCommands(t *testing.T) { test_utils.EnsureCommandContainsAll(g, t, cliCmd, "SERVICE,COUNT,SIZE,cache-1,cache-2", configArg, file, "get", "caches", "-c", context.ClusterName) + // test cache-storage + test_utils.EnsureCommandContainsAll(g, t, cliCmd, "LOCKS GRANTED,", configArg, file, + "get", "cache-storage", cacheName, "-c", context.ClusterName) + + // test cache-access + test_utils.EnsureCommandContainsAll(g, t, cliCmd, "EVICTIONS,", configArg, file, + "get", "cache-access", cacheName, "-c", context.ClusterName) + + // test cache-indexes + test_utils.EnsureCommandContainsAll(g, t, cliCmd, "Total Indexing Bytes,", configArg, file, + "get", "cache-indexes", cacheName, "-c", context.ClusterName) + // test write-behind test_utils.EnsureCommandContainsAll(g, t, cliCmd, "PartitionedCacheWriteBehind,QUEUE SIZE,cache-store-1", configArg, file, "get", "cache-stores", "cache-store-1", "-s", "PartitionedCacheWriteBehind", "-c", context.ClusterName)