1   package org.apache.jcs.access;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.BufferedReader;
23  import java.io.InputStreamReader;
24  import java.util.Iterator;
25  import java.util.Random;
26  import java.util.StringTokenizer;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  import org.apache.jcs.JCS;
32  import org.apache.jcs.engine.ElementAttributes;
33  import org.apache.jcs.engine.behavior.IElementAttributes;
34  import org.apache.jcs.engine.control.CompositeCacheManager;
35  import org.apache.jcs.engine.control.event.ElementEventHandlerMockImpl;
36  
37  /***
38   * Allows the user to run common cache commands from the command line for a test
39   * cache.
40   *
41   * This also provide basic methods for use in unit tests.
42   *
43   */
44  public class TestCacheAccess
45  {
46      private final static Log log = LogFactory.getLog( TestCacheAccess.class );
47  
48      private JCS cache_control = null;
49  
50      private static boolean isSysOut = false;
51  
52      /***
53       * Construct and initialize the cachecontrol based on the config file.
54       *
55       */
56      public TestCacheAccess()
57      {
58          this( "testCache1" );
59      }
60  
61      /***
62       * @param regionName the name of the region.
63       */
64      public TestCacheAccess( String regionName )
65      {
66          try
67          {
68              cache_control = JCS.getInstance( regionName );
69          }
70          catch ( Exception e )
71          {
72              log.error( "Problem getting cache instance", e );
73              p( e.toString() );
74          }
75      }
76  
77      /***
78       * This is the main loop called by the main method.
79       */
80      public void runLoop()
81      {
82  
83          try
84          {
85              try
86              {
87  
88                  // process user input till done
89                  boolean notDone = true;
90                  String message = null;
91                  // wait to dispose
92                  BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
93  
94                  help();
95  
96                  while ( notDone )
97                  {
98                      p( "enter command:" );
99  
100                     message = br.readLine();
101 
102                     if ( message.startsWith( "help" ) )
103                     {
104                         help();
105                     }
106                     else if ( message.startsWith( "gc" ) )
107                     {
108                         System.gc();
109                     }
110                     else if ( message.startsWith( "getAttributeNames" ) )
111                     {
112                         long n_start = System.currentTimeMillis();
113                         String groupName = null;
114                         StringTokenizer toke = new StringTokenizer( message );
115                         int tcnt = 0;
116                         while ( toke.hasMoreElements() )
117                         {
118                             tcnt++;
119                             String t = (String) toke.nextElement();
120                             if ( tcnt == 2 )
121                             {
122                                 groupName = t.trim();
123                             }
124                         }
125                         getAttributeNames( groupName );
126                         long n_end = System.currentTimeMillis();
127                         p( "---got attrNames for " + groupName + " in " + String.valueOf( n_end - n_start )
128                             + " millis ---" );
129                     }
130                     else if ( message.startsWith( "shutDown" ) )
131                     {
132                         CompositeCacheManager.getInstance().shutDown();
133                         //cache_control.dispose();
134                         notDone = false;
135                         //System.exit( -1 );
136                         return;
137                     }
138                     else
139 
140                     /////////////////////////////////////////////////////////////////////
141                     // get multiple from a region
142                     if ( message.startsWith( "getm" ) )
143                     {
144 
145                         int num = 0;
146                         boolean show = true;
147 
148                         StringTokenizer toke = new StringTokenizer( message );
149                         int tcnt = 0;
150                         while ( toke.hasMoreElements() )
151                         {
152                             tcnt++;
153                             String t = (String) toke.nextElement();
154                             if ( tcnt == 2 )
155                             {
156                                 try
157                                 {
158                                     num = Integer.parseInt( t.trim() );
159                                 }
160                                 catch ( NumberFormatException nfe )
161                                 {
162                                     p( t + "not a number" );
163                                 }
164                             }
165                             else if ( tcnt == 3 )
166                             {
167                                 show = new Boolean( t ).booleanValue();
168                             }
169                         }
170 
171                         if ( tcnt < 2 )
172                         {
173                             p( "usage: get numbertoget show values[true|false]" );
174                         }
175                         else
176                         {
177                             getMultiple( num, show );
178                         }
179                     }
180                     else
181 
182                     /////////////////////////////////////////////////////////////////////
183                     if ( message.startsWith( "getg" ) )
184                     {
185 
186                         String key = null;
187                         String group = null;
188                         boolean show = true;
189 
190                         StringTokenizer toke = new StringTokenizer( message );
191                         int tcnt = 0;
192                         while ( toke.hasMoreElements() )
193                         {
194                             tcnt++;
195                             String t = (String) toke.nextElement();
196                             if ( tcnt == 2 )
197                             {
198                                 key = t.trim();
199                             }
200                             else if ( tcnt == 3 )
201                             {
202                                 group = t.trim();
203                             }
204                             else if ( tcnt == 4 )
205                             {
206                                 show = new Boolean( t ).booleanValue();
207                             }
208                         }
209 
210                         if ( tcnt < 2 )
211                         {
212                             p( "usage: get key show values[true|false]" );
213                         }
214                         else
215                         {
216 
217                             long n_start = System.currentTimeMillis();
218                             try
219                             {
220                                 Object obj = cache_control.getFromGroup( key, group );
221                                 if ( show && obj != null )
222                                 {
223                                     p( obj.toString() );
224                                 }
225                             }
226                             catch ( Exception e )
227                             {
228                                 log.error( e );
229                             }
230                             long n_end = System.currentTimeMillis();
231                             p( "---got " + key + " from group " + group + " in " + String.valueOf( n_end - n_start )
232                                 + " millis ---" );
233                         }
234                     }
235                     else
236 
237                     /////////////////////////////////////////////////////////////////////
238                     if ( message.startsWith( "getag" ) )
239                     {
240                         // get auto from group
241 
242                         int num = 0;
243                         String group = null;
244                         boolean show = true;
245 
246                         StringTokenizer toke = new StringTokenizer( message );
247                         int tcnt = 0;
248                         while ( toke.hasMoreElements() )
249                         {
250                             tcnt++;
251                             String t = (String) toke.nextElement();
252                             if ( tcnt == 2 )
253                             {
254                                 num = Integer.parseInt( t.trim() );
255                             }
256                             else if ( tcnt == 3 )
257                             {
258                                 group = t.trim();
259                             }
260                             else if ( tcnt == 4 )
261                             {
262                                 show = new Boolean( t ).booleanValue();
263                             }
264                         }
265 
266                         if ( tcnt < 2 )
267                         {
268                             p( "usage: get key show values[true|false]" );
269                         }
270                         else
271                         {
272 
273                             long n_start = System.currentTimeMillis();
274                             try
275                             {
276                                 for ( int a = 0; a < num; a++ )
277                                 {
278                                     Object obj = cache_control.getFromGroup( "keygr" + a, group );
279                                     if ( show && obj != null )
280                                     {
281                                         p( obj.toString() );
282                                     }
283                                 }
284                             }
285                             catch ( Exception e )
286                             {
287                                 log.error( e );
288                             }
289                             long n_end = System.currentTimeMillis();
290                             p( "---got " + num + " from group " + group + " in " + String.valueOf( n_end - n_start )
291                                 + " millis ---" );
292                         }
293                     }
294                     else
295 
296                     /////////////////////////////////////////////////////////////////////
297                     if ( message.startsWith( "get" ) )
298                     {
299                         // plain old get
300 
301                         String key = null;
302                         boolean show = true;
303 
304                         StringTokenizer toke = new StringTokenizer( message );
305                         int tcnt = 0;
306                         while ( toke.hasMoreElements() )
307                         {
308                             tcnt++;
309                             String t = (String) toke.nextElement();
310                             if ( tcnt == 2 )
311                             {
312                                 key = t.trim();
313                             }
314                             else if ( tcnt == 3 )
315                             {
316                                 show = new Boolean( t ).booleanValue();
317                             }
318                         }
319 
320                         if ( tcnt < 2 )
321                         {
322                             p( "usage: get key show values[true|false]" );
323                         }
324                         else
325                         {
326 
327                             long n_start = System.currentTimeMillis();
328                             try
329                             {
330                                 Object obj = cache_control.get( key );
331                                 if ( show && obj != null )
332                                 {
333                                     p( obj.toString() );
334                                 }
335                             }
336                             catch ( Exception e )
337                             {
338                                 log.error( e );
339                             }
340                             long n_end = System.currentTimeMillis();
341                             p( "---got " + key + " in " + String.valueOf( n_end - n_start ) + " millis ---" );
342                         }
343                     }
344                     else if ( message.startsWith( "putg" ) )
345                     {
346 
347                         String group = null;
348                         String key = null;
349                         StringTokenizer toke = new StringTokenizer( message );
350                         int tcnt = 0;
351                         while ( toke.hasMoreElements() )
352                         {
353                             tcnt++;
354                             String t = (String) toke.nextElement();
355                             if ( tcnt == 2 )
356                             {
357                                 key = t.trim();
358                             }
359                             else if ( tcnt == 3 )
360                             {
361                                 group = t.trim();
362                             }
363                         }
364 
365                         if ( tcnt < 3 )
366                         {
367                             p( "usage: putg key group" );
368                         }
369                         else
370                         {
371                             long n_start = System.currentTimeMillis();
372                             cache_control.putInGroup( key, group,
373                                                       "data from putg ----asdfasfas-asfasfas-asfas in group " + group );
374                             long n_end = System.currentTimeMillis();
375                             p( "---put " + key + " in group " + group + " in " + String.valueOf( n_end - n_start )
376                                 + " millis ---" );
377                         }
378                     }
379                     else
380 
381                     // put automatically
382                     if ( message.startsWith( "putag" ) )
383                     {
384 
385                         String group = null;
386                         int num = 0;
387                         StringTokenizer toke = new StringTokenizer( message );
388                         int tcnt = 0;
389                         while ( toke.hasMoreElements() )
390                         {
391                             tcnt++;
392                             String t = (String) toke.nextElement();
393                             if ( tcnt == 2 )
394                             {
395                                 num = Integer.parseInt( t.trim() );
396                             }
397                             else if ( tcnt == 3 )
398                             {
399                                 group = t.trim();
400                             }
401                         }
402 
403                         if ( tcnt < 3 )
404                         {
405                             p( "usage: putag num group" );
406                         }
407                         else
408                         {
409                             long n_start = System.currentTimeMillis();
410                             for ( int a = 0; a < num; a++ )
411                             {
412                                 cache_control.putInGroup( "keygr" + a, group, "data " + a
413                                     + " from putag ----asdfasfas-asfasfas-asfas in group " + group );
414                             }
415                             long n_end = System.currentTimeMillis();
416                             p( "---put " + num + " in group " + group + " in " + String.valueOf( n_end - n_start )
417                                 + " millis ---" );
418                         }
419                     }
420                     else
421 
422                     /////////////////////////////////////////////////////////////////////
423                     if ( message.startsWith( "putm" ) )
424                     {
425                         String numS = message.substring( message.indexOf( " " ) + 1, message.length() );
426                         int num = Integer.parseInt( numS.trim() );
427                         if ( numS == null )
428                         {
429                             p( "usage: putm numbertoput" );
430                         }
431                         else
432                         {
433                             putMultiple( num );
434                         }
435                     }
436                     else
437 
438                     /////////////////////////////////////////////////////////////////////
439                     if ( message.startsWith( "pute" ) )
440                     {
441                         String numS = message.substring( message.indexOf( " " ) + 1, message.length() );
442                         int num = Integer.parseInt( numS.trim() );
443                         if ( numS == null )
444                         {
445                             p( "usage: putme numbertoput" );
446                         }
447                         else
448                         {
449                             long n_start = System.currentTimeMillis();
450                             for ( int n = 0; n < num; n++ )
451                             {
452                                 IElementAttributes attrp = cache_control.getDefaultElementAttributes();
453                                 ElementEventHandlerMockImpl hand = new ElementEventHandlerMockImpl();
454                                 attrp.addElementEventHandler( hand );
455                                 cache_control.put( "key" + n, "data" + n + " put from ta = junk", attrp );
456                             }
457                             long n_end = System.currentTimeMillis();
458                             p( "---put " + num + " in " + String.valueOf( n_end - n_start ) + " millis ---" );
459                         }
460                     }
461                     else if ( message.startsWith( "put" ) )
462                     {
463 
464                         String key = null;
465                         String val = null;
466                         StringTokenizer toke = new StringTokenizer( message );
467                         int tcnt = 0;
468                         while ( toke.hasMoreElements() )
469                         {
470                             tcnt++;
471                             String t = (String) toke.nextElement();
472                             if ( tcnt == 2 )
473                             {
474                                 key = t.trim();
475                             }
476                             else if ( tcnt == 3 )
477                             {
478                                 val = t.trim();
479                             }
480                         }
481 
482                         if ( tcnt < 3 )
483                         {
484                             p( "usage: put key val" );
485                         }
486                         else
487                         {
488 
489                             long n_start = System.currentTimeMillis();
490                             cache_control.put( key, val );
491                             long n_end = System.currentTimeMillis();
492                             p( "---put " + key + " | " + val + " in " + String.valueOf( n_end - n_start )
493                                 + " millis ---" );
494                         }
495                     }
496                     /////////////////////////////////////////////////////////////////////
497                     if ( message.startsWith( "removem" ) )
498                     {
499                         String numS = message.substring( message.indexOf( " " ) + 1, message.length() );
500                         int num = Integer.parseInt( numS.trim() );
501                         if ( numS == null )
502                         {
503                             p( "usage: removem numbertoremove" );
504                         }
505                         else
506                         {
507                             removeMultiple( num );
508                         }
509                     }
510 
511                     else if ( message.startsWith( "removeall" ) )
512                     {
513                         cache_control.clear();
514                         p( "removed all" );
515                     }
516                     else if ( message.startsWith( "remove" ) )
517                     {
518                         String key = message.substring( message.indexOf( " " ) + 1, message.length() );
519                         cache_control.remove( key );
520                         p( "removed " + key );
521                     }
522                     else if ( message.startsWith( "deattr" ) )
523                     {
524                         IElementAttributes ae = cache_control.getDefaultElementAttributes();
525                         p( "Default IElementAttributes " + ae );
526                     }
527                     else if ( message.startsWith( "cloneattr" ) )
528                     {
529                         String numS = message.substring( message.indexOf( " " ) + 1, message.length() );
530                         int num = Integer.parseInt( numS.trim() );
531                         if ( numS == null )
532                         {
533                             p( "usage: put numbertoput" );
534                         }
535                         else
536                         {
537                             IElementAttributes attrp = new ElementAttributes();
538                             long n_start = System.currentTimeMillis();
539                             for ( int n = 0; n < num; n++ )
540                             {
541                                 attrp.copy();
542                             }
543                             long n_end = System.currentTimeMillis();
544                             p( "---cloned attr " + num + " in " + String.valueOf( n_end - n_start ) + " millis ---" );
545                         }
546                     }
547                     else if ( message.startsWith( "switch" ) )
548                     {
549                         String name = message.substring( message.indexOf( " " ) + 1, message.length() );
550 
551                         setRegion( name );
552                         p( "switched to cache = " + name );
553                         p( cache_control.toString() );
554                     }
555                     else if ( message.startsWith( "stats" ) )
556                     {
557                         p( cache_control.getStats() );
558                     }
559                     else if ( message.startsWith( "gc" ) )
560                     {
561                         System.gc();
562                         p( "Called system.gc()" );
563                     }
564                     else if ( message.startsWith( "random" ) )
565                         if ( message.startsWith( "random" ) )
566                         {
567                             String rangeS = "";
568                             String numOpsS = "";
569                             boolean show = true;
570 
571                             StringTokenizer toke = new StringTokenizer( message );
572                             int tcnt = 0;
573                             while ( toke.hasMoreElements() )
574                             {
575                                 tcnt++;
576                                 String t = (String) toke.nextElement();
577                                 if ( tcnt == 2 )
578                                 {
579                                     rangeS = t.trim();
580                                 }
581                                 else if ( tcnt == 3 )
582                                 {
583                                     numOpsS = t.trim();
584                                 }
585                                 else if ( tcnt == 4 )
586                                 {
587                                     show = new Boolean( t ).booleanValue();
588                                 }
589                             }
590 
591                             String numS = message.substring( message.indexOf( " " ) + 1, message.length() );
592 
593                             int range = 0;
594                             int numOps = 0;
595                             try
596                             {
597                                 range = Integer.parseInt( rangeS.trim() );
598                                 numOps = Integer.parseInt( numOpsS.trim() );
599                             }
600                             catch ( Exception e )
601                             {
602                                 p( "usage: random range numOps show" );
603                                 p( "ex.  random 100 1000 false" );
604                             }
605                             if ( numS == null )
606                             {
607                                 p( "usage: random range numOps show" );
608                                 p( "ex.  random 100 1000 false" );
609                             }
610                             else
611                             {
612                                 random( range, numOps, show );
613                             }
614                         }
615 
616                 }
617             }
618             catch ( Exception e )
619             {
620                 p( e.toString() );
621                 e.printStackTrace( System.out );
622             }
623 
624         }
625         catch ( Exception e )
626         {
627             p( e.toString() );
628             e.printStackTrace( System.out );
629         }
630 
631     } // end runLoop
632 
633     /***
634      * Test harness.
635      *
636      * @param args
637      *            The command line arguments
638      */
639     public static void main( String[] args )
640     {
641         isSysOut = true;
642         String ccfFileName = args[0];
643         if ( ccfFileName != null )
644         {
645             JCS.setConfigFilename( ccfFileName );
646         }
647         TestCacheAccess tca = new TestCacheAccess( "testCache1" );
648         tca.runLoop();
649     }
650 
651     // end main
652     /////////////////////////////////////////////////////////////////////////////
653 
654     /***
655      * Gets multiple items from the cache with keys of the form key1, key2, key3
656      * up to key[num].
657      *
658      * @param num
659      *            int
660      */
661     public void getMultiple( int num )
662     {
663         getMultiple( num, false );
664     }
665 
666     /***
667      * @param num
668      * @param show
669      */
670     public void getMultiple( int num, boolean show )
671     {
672         long n_start = System.currentTimeMillis();
673         for ( int n = 0; n < num; n++ )
674         {
675             try
676             {
677                 Object obj = cache_control.get( "key" + n );
678                 if ( show && obj != null )
679                 {
680                     p( obj.toString() );
681                 }
682             }
683             catch ( Exception e )
684             {
685                 log.error( e );
686             }
687         }
688         long n_end = System.currentTimeMillis();
689         p( "---got " + num + " in " + String.valueOf( n_end - n_start ) + " millis ---" );
690     }
691 
692     /***
693      * Puts multiple items into the cache.
694      *
695      * @param num
696      *            int
697      */
698     public void putMultiple( int num )
699     {
700         try
701         {
702             long n_start = System.currentTimeMillis();
703             for ( int n = 0; n < num; n++ )
704             {
705                 cache_control.put( "key" + n, "data" + n + " put from ta = junk" );
706             }
707             long n_end = System.currentTimeMillis();
708             p( "---put " + num + " in " + String.valueOf( n_end - n_start ) + " millis ---" );
709         }
710         catch ( Exception e )
711         {
712             log.error( e );
713         }
714     }
715 
716     /***
717      * Removes multiple items from the cache.
718      *
719      * @param num
720      *            int
721      */
722     public void removeMultiple( int num )
723     {
724         try
725         {
726             long n_start = System.currentTimeMillis();
727             for ( int n = 0; n < num; n++ )
728             {
729                 cache_control.remove( "key" + n );
730             }
731             long n_end = System.currentTimeMillis();
732             p( "---removed " + num + " in " + String.valueOf( n_end - n_start ) + " millis ---" );
733         }
734         catch ( Exception e )
735         {
736             log.error( e );
737         }
738     }
739 
740     /***
741      * The random method performs numOps number of operations. The operations
742      * will be a mix of puts, gets, and removes. The key range will be from 0 to
743      * range.
744      *
745      * @param range
746      *            int The end of the key range.
747      * @param numOps
748      *            int The number of operations to perform
749      */
750     public void random( int range, int numOps )
751     {
752         random( range, numOps, false );
753     }
754 
755     /***
756      * @param range
757      * @param numOps
758      * @param show
759      */
760     public void random( int range, int numOps, boolean show )
761     {
762         try
763         {
764             for ( int i = 0; i < numOps; i++ )
765             {
766                 Random ran = new Random( i );
767                 int n = ran.nextInt( 4 );
768                 int kn = ran.nextInt( range );
769                 String key = "key" + kn;
770                 if ( n == 1 )
771                 {
772                     cache_control.put( key, "data" + i + " junk asdfffffffadfasdfasf " + kn + ":" + n );
773                     if ( show )
774                     {
775                         p( "put " + key );
776                     }
777                 }
778                 else if ( n == 2 )
779                 {
780                     cache_control.remove( key );
781                     if ( show )
782                     {
783                         p( "removed " + key );
784                     }
785                 }
786                 else
787                 {
788                     // slightly greater chance of get
789                     Object obj = cache_control.get( key );
790                     if ( show && obj != null )
791                     {
792                         p( obj.toString() );
793                     }
794                 }
795 
796                 if ( i % 10000 == 0 )
797                 {
798                     p( cache_control.getStats() );
799                 }
800 
801             }
802             p( "Finished random cycle of " + numOps );
803         }
804         catch ( Exception e )
805         {
806             p( e.toString() );
807             e.printStackTrace( System.out );
808         }
809     }
810 
811     /***
812      * Sets the region to be used by test methods.
813      *
814      * @param name
815      *            String -- Name of region
816      */
817     public void setRegion( String name )
818     {
819         try
820         {
821             cache_control = JCS.getInstance( name );
822         }
823         catch ( Exception e )
824         {
825             p( e.toString() );
826             e.printStackTrace( System.out );
827         }
828 
829     }
830 
831     /////////////////////////////////////////////////////////////////////////////
832     /***
833      * The tester will print to the console if isSysOut is true, else it will
834      * log. It is false by default. When run via the main method, isSysOut will
835      * be set to true
836      *
837      * @param s
838      *            String to print or log
839      */
840     public static void p( String s )
841     {
842         if ( isSysOut )
843         {
844             System.out.println( s );
845         }
846         else
847         {
848             if ( log.isDebugEnabled() )
849             {
850                 log.debug( s );
851             }
852         }
853     }
854 
855     /***
856      * Displays usage information for command line testing.
857      */
858     public static void help()
859     {
860         p( "\n\n\n\n" );
861         p( "type 'shutDown' to shutdown the cache" );
862         p( "type 'getm num show[false|true]' to get num automatically from a region" );
863         p( "type 'putm num' to put num automatically to a region" );
864         p( "type 'removeall' to remove all items in a region" );
865         p( "type 'remove key' to remove" );
866         p( "type 'removem num' to remove a number automatically" );
867         p( "type 'get key show' to get" );
868         p( "type 'getg key group show' to get" );
869         p( "type 'getag num group show' to get automatically from a group" );
870         p( "type 'getAttributeNames group' to get a list og the group elements" );
871         p( "type 'putg key group val' to put" );
872         p( "type 'putag num group' to put automatically from a group" );
873         p( "type 'put key val' to put" );
874         p( "type 'stats' to get stats" );
875         p( "type 'deattr' to get the default element attributes" );
876         p( "type 'cloneattr num' to clone attr" );
877         p( "type 'random range numOps' to put, get, and remove randomly" );
878         p( "type 'switch name' to switch to this region name" );
879         p( "type 'gc' to call System.gc()" );
880         p( "type 'help' for commands" );
881 
882     }
883 
884     /***
885      * Gets the attributeNames attribute of the TestCacheAccess class
886      *
887      * @param groupName
888      */
889     public void getAttributeNames( String groupName )
890     {
891         Iterator iter = cache_control.getGroupKeys( groupName ).iterator();
892 
893         while ( iter.hasNext() )
894         {
895             p( "=" + (String) iter.next() );
896         }
897     }
898 
899 } // end class