001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.store.kahadb;
018
019import org.apache.activemq.broker.BrokerService;
020import org.apache.activemq.broker.ConnectionContext;
021import org.apache.activemq.broker.LockableServiceSupport;
022import org.apache.activemq.broker.Locker;
023import org.apache.activemq.broker.jmx.AnnotatedMBean;
024import org.apache.activemq.broker.jmx.PersistenceAdapterView;
025import org.apache.activemq.broker.scheduler.JobSchedulerStore;
026import org.apache.activemq.command.ActiveMQDestination;
027import org.apache.activemq.command.ActiveMQQueue;
028import org.apache.activemq.command.ActiveMQTopic;
029import org.apache.activemq.command.LocalTransactionId;
030import org.apache.activemq.command.ProducerId;
031import org.apache.activemq.command.TransactionId;
032import org.apache.activemq.command.XATransactionId;
033import org.apache.activemq.protobuf.Buffer;
034import org.apache.activemq.store.JournaledStore;
035import org.apache.activemq.store.MessageStore;
036import org.apache.activemq.store.NoLocalSubscriptionAware;
037import org.apache.activemq.store.PersistenceAdapter;
038import org.apache.activemq.store.PersistenceAdapterStatistics;
039import org.apache.activemq.store.SharedFileLocker;
040import org.apache.activemq.store.TopicMessageStore;
041import org.apache.activemq.store.TransactionIdTransformer;
042import org.apache.activemq.store.TransactionIdTransformerAware;
043import org.apache.activemq.store.TransactionStore;
044import org.apache.activemq.store.kahadb.data.KahaLocalTransactionId;
045import org.apache.activemq.store.kahadb.data.KahaTransactionInfo;
046import org.apache.activemq.store.kahadb.data.KahaXATransactionId;
047import org.apache.activemq.store.kahadb.disk.journal.Journal.JournalDiskSyncStrategy;
048import org.apache.activemq.usage.SystemUsage;
049import org.apache.activemq.util.ServiceStopper;
050
051import javax.management.ObjectName;
052import java.io.File;
053import java.io.IOException;
054import java.util.Set;
055import java.util.concurrent.Callable;
056
057import static org.apache.activemq.broker.jmx.BrokerMBeanSupport.createPersistenceAdapterName;
058
059/**
060 * An implementation of {@link PersistenceAdapter} designed for use with
061 * KahaDB - Embedded Lightweight Non-Relational Database
062 *
063 * @org.apache.xbean.XBean element="kahaDB"
064 *
065 */
066public class KahaDBPersistenceAdapter extends LockableServiceSupport implements PersistenceAdapter,
067    JournaledStore, TransactionIdTransformerAware, NoLocalSubscriptionAware {
068
069    private final KahaDBStore letter = new KahaDBStore();
070
071    /**
072     * @param context
073     * @throws IOException
074     * @see org.apache.activemq.store.PersistenceAdapter#beginTransaction(org.apache.activemq.broker.ConnectionContext)
075     */
076    @Override
077    public void beginTransaction(ConnectionContext context) throws IOException {
078        this.letter.beginTransaction(context);
079    }
080
081    /**
082     * @param cleanup
083     * @throws IOException
084     * @see org.apache.activemq.store.PersistenceAdapter#checkpoint(boolean)
085     */
086    @Override
087    public void checkpoint(boolean cleanup) throws IOException {
088        this.letter.checkpoint(cleanup);
089    }
090
091    /**
092     * @param context
093     * @throws IOException
094     * @see org.apache.activemq.store.PersistenceAdapter#commitTransaction(org.apache.activemq.broker.ConnectionContext)
095     */
096    @Override
097    public void commitTransaction(ConnectionContext context) throws IOException {
098        this.letter.commitTransaction(context);
099    }
100
101    /**
102     * @param destination
103     * @return MessageStore
104     * @throws IOException
105     * @see org.apache.activemq.store.PersistenceAdapter#createQueueMessageStore(org.apache.activemq.command.ActiveMQQueue)
106     */
107    @Override
108    public MessageStore createQueueMessageStore(ActiveMQQueue destination) throws IOException {
109        return this.letter.createQueueMessageStore(destination);
110    }
111
112    /**
113     * @param destination
114     * @return TopicMessageStore
115     * @throws IOException
116     * @see org.apache.activemq.store.PersistenceAdapter#createTopicMessageStore(org.apache.activemq.command.ActiveMQTopic)
117     */
118    @Override
119    public TopicMessageStore createTopicMessageStore(ActiveMQTopic destination) throws IOException {
120        return this.letter.createTopicMessageStore(destination);
121    }
122
123    /**
124     * @return TransactionStore
125     * @throws IOException
126     * @see org.apache.activemq.store.PersistenceAdapter#createTransactionStore()
127     */
128    @Override
129    public TransactionStore createTransactionStore() throws IOException {
130        return this.letter.createTransactionStore();
131    }
132
133    /**
134     * @throws IOException
135     * @see org.apache.activemq.store.PersistenceAdapter#deleteAllMessages()
136     */
137    @Override
138    public void deleteAllMessages() throws IOException {
139        this.letter.deleteAllMessages();
140    }
141
142    /**
143     * @return destinations
144     * @see org.apache.activemq.store.PersistenceAdapter#getDestinations()
145     */
146    @Override
147    public Set<ActiveMQDestination> getDestinations() {
148        return this.letter.getDestinations();
149    }
150
151    /**
152     * @return lastMessageBrokerSequenceId
153     * @throws IOException
154     * @see org.apache.activemq.store.PersistenceAdapter#getLastMessageBrokerSequenceId()
155     */
156    @Override
157    public long getLastMessageBrokerSequenceId() throws IOException {
158        return this.letter.getLastMessageBrokerSequenceId();
159    }
160
161    @Override
162    public long getLastProducerSequenceId(ProducerId id) throws IOException {
163        return this.letter.getLastProducerSequenceId(id);
164    }
165
166    @Override
167    public void allowIOResumption() {
168        this.letter.allowIOResumption();
169    }
170
171    /**
172     * @param destination
173     * @see org.apache.activemq.store.PersistenceAdapter#removeQueueMessageStore(org.apache.activemq.command.ActiveMQQueue)
174     */
175    @Override
176    public void removeQueueMessageStore(ActiveMQQueue destination) {
177        this.letter.removeQueueMessageStore(destination);
178    }
179
180    /**
181     * @param destination
182     * @see org.apache.activemq.store.PersistenceAdapter#removeTopicMessageStore(org.apache.activemq.command.ActiveMQTopic)
183     */
184    @Override
185    public void removeTopicMessageStore(ActiveMQTopic destination) {
186        this.letter.removeTopicMessageStore(destination);
187    }
188
189    /**
190     * @param context
191     * @throws IOException
192     * @see org.apache.activemq.store.PersistenceAdapter#rollbackTransaction(org.apache.activemq.broker.ConnectionContext)
193     */
194    @Override
195    public void rollbackTransaction(ConnectionContext context) throws IOException {
196        this.letter.rollbackTransaction(context);
197    }
198
199    /**
200     * @param brokerName
201     * @see org.apache.activemq.store.PersistenceAdapter#setBrokerName(java.lang.String)
202     */
203    @Override
204    public void setBrokerName(String brokerName) {
205        this.letter.setBrokerName(brokerName);
206    }
207
208    /**
209     * @param usageManager
210     * @see org.apache.activemq.store.PersistenceAdapter#setUsageManager(org.apache.activemq.usage.SystemUsage)
211     */
212    @Override
213    public void setUsageManager(SystemUsage usageManager) {
214        this.letter.setUsageManager(usageManager);
215    }
216
217    /**
218     * @return the size of the store
219     * @see org.apache.activemq.store.PersistenceAdapter#size()
220     */
221    @Override
222    public long size() {
223        return this.letter.isStarted() ? this.letter.size() : 0l;
224    }
225
226    /**
227     * @throws Exception
228     * @see org.apache.activemq.Service#start()
229     */
230    @Override
231    public void doStart() throws Exception {
232        this.letter.start();
233
234        if (brokerService != null && brokerService.isUseJmx()) {
235            PersistenceAdapterView view = new PersistenceAdapterView(this);
236            view.setInflightTransactionViewCallable(new Callable<String>() {
237                @Override
238                public String call() throws Exception {
239                    return letter.getTransactions();
240                }
241            });
242            view.setDataViewCallable(new Callable<String>() {
243                @Override
244                public String call() throws Exception {
245                    return letter.getJournal().getFileMap().keySet().toString();
246                }
247            });
248
249            view.setPersistenceAdapterStatistics(letter.persistenceAdapterStatistics);
250
251            AnnotatedMBean.registerMBean(brokerService.getManagementContext(), view,
252                    createPersistenceAdapterName(brokerService.getBrokerObjectName().toString(), toString()));
253        }
254    }
255
256    /**
257     * @throws Exception
258     * @see org.apache.activemq.Service#stop()
259     */
260    @Override
261    public void doStop(ServiceStopper stopper) throws Exception {
262        this.letter.stop();
263
264        if (brokerService != null && brokerService.isUseJmx()) {
265            ObjectName brokerObjectName = brokerService.getBrokerObjectName();
266            brokerService.getManagementContext().unregisterMBean(createPersistenceAdapterName(brokerObjectName.toString(), toString()));
267        }
268    }
269
270    /**
271     * Get the journalMaxFileLength
272     *
273     * @return the journalMaxFileLength
274     */
275    @Override
276    public int getJournalMaxFileLength() {
277        return this.letter.getJournalMaxFileLength();
278    }
279
280    /**
281     * When set using Xbean, values of the form "20 Mb", "1024kb", and "1g" can
282     * be used
283     *
284     * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryIntPropertyEditor"
285     */
286    public void setJournalMaxFileLength(int journalMaxFileLength) {
287        this.letter.setJournalMaxFileLength(journalMaxFileLength);
288    }
289
290    /**
291     * Set the max number of producers (LRU cache) to track for duplicate sends
292     */
293    public void setMaxFailoverProducersToTrack(int maxFailoverProducersToTrack) {
294        this.letter.setMaxFailoverProducersToTrack(maxFailoverProducersToTrack);
295    }
296
297    public int getMaxFailoverProducersToTrack() {
298        return this.letter.getMaxFailoverProducersToTrack();
299    }
300
301    /**
302     * set the audit window depth for duplicate suppression (should exceed the max transaction
303     * batch)
304     */
305    public void setFailoverProducersAuditDepth(int failoverProducersAuditDepth) {
306        this.letter.setFailoverProducersAuditDepth(failoverProducersAuditDepth);
307    }
308
309    public int getFailoverProducersAuditDepth() {
310        return this.letter.getFailoverProducersAuditDepth();
311    }
312
313    /**
314     * Get the checkpointInterval
315     *
316     * @return the checkpointInterval
317     */
318    public long getCheckpointInterval() {
319        return this.letter.getCheckpointInterval();
320    }
321
322    /**
323     * Set the checkpointInterval
324     *
325     * @param checkpointInterval
326     *            the checkpointInterval to set
327     */
328    public void setCheckpointInterval(long checkpointInterval) {
329        this.letter.setCheckpointInterval(checkpointInterval);
330    }
331
332    /**
333     * Get the cleanupInterval
334     *
335     * @return the cleanupInterval
336     */
337    public long getCleanupInterval() {
338        return this.letter.getCleanupInterval();
339    }
340
341    /**
342     * Set the cleanupInterval
343     *
344     * @param cleanupInterval
345     *            the cleanupInterval to set
346     */
347    public void setCleanupInterval(long cleanupInterval) {
348        this.letter.setCleanupInterval(cleanupInterval);
349    }
350
351    /**
352     * Get the indexWriteBatchSize
353     *
354     * @return the indexWriteBatchSize
355     */
356    public int getIndexWriteBatchSize() {
357        return this.letter.getIndexWriteBatchSize();
358    }
359
360    /**
361     * Set the indexWriteBatchSize
362     * When set using Xbean, values of the form "20 Mb", "1024kb", and "1g" can be used
363     * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryPropertyEditor"
364     * @param indexWriteBatchSize
365     *            the indexWriteBatchSize to set
366     */
367    public void setIndexWriteBatchSize(int indexWriteBatchSize) {
368        this.letter.setIndexWriteBatchSize(indexWriteBatchSize);
369    }
370
371    /**
372     * Get the journalMaxWriteBatchSize
373     *
374     * @return the journalMaxWriteBatchSize
375     */
376    public int getJournalMaxWriteBatchSize() {
377        return this.letter.getJournalMaxWriteBatchSize();
378    }
379
380    /**
381     * Set the journalMaxWriteBatchSize
382     *  * When set using Xbean, values of the form "20 Mb", "1024kb", and "1g" can be used
383     * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryPropertyEditor"
384     * @param journalMaxWriteBatchSize
385     *            the journalMaxWriteBatchSize to set
386     */
387    public void setJournalMaxWriteBatchSize(int journalMaxWriteBatchSize) {
388        this.letter.setJournalMaxWriteBatchSize(journalMaxWriteBatchSize);
389    }
390
391    /**
392     * Get the enableIndexWriteAsync
393     *
394     * @return the enableIndexWriteAsync
395     */
396    public boolean isEnableIndexWriteAsync() {
397        return this.letter.isEnableIndexWriteAsync();
398    }
399
400    /**
401     * Set the enableIndexWriteAsync
402     *
403     * @param enableIndexWriteAsync
404     *            the enableIndexWriteAsync to set
405     */
406    public void setEnableIndexWriteAsync(boolean enableIndexWriteAsync) {
407        this.letter.setEnableIndexWriteAsync(enableIndexWriteAsync);
408    }
409
410    /**
411     * Get the PersistenceAdapterStatistics
412     *
413     * @return the persistenceAdapterStatistics
414     */
415    public PersistenceAdapterStatistics getPersistenceAdapterStatistics() {
416        return this.letter.getPersistenceAdapterStatistics();
417    }
418
419    /**
420     * Get the directory
421     *
422     * @return the directory
423     */
424    @Override
425    public File getDirectory() {
426        return this.letter.getDirectory();
427    }
428
429    /**
430     * @param dir
431     * @see org.apache.activemq.store.PersistenceAdapter#setDirectory(java.io.File)
432     */
433    @Override
434    public void setDirectory(File dir) {
435        this.letter.setDirectory(dir);
436    }
437
438    /**
439     * @return the currently configured location of the KahaDB index files.
440     */
441    public File getIndexDirectory() {
442        return this.letter.getIndexDirectory();
443    }
444
445    /**
446     * Sets the directory where KahaDB index files should be written.
447     *
448     * @param indexDirectory
449     *        the directory where the KahaDB store index files should be written.
450     */
451    public void setIndexDirectory(File indexDirectory) {
452        this.letter.setIndexDirectory(indexDirectory);
453    }
454
455    /**
456     * Get the enableJournalDiskSyncs
457     * @deprecated use {@link #getJournalDiskSyncStrategy} instead
458     * @return the enableJournalDiskSyncs
459     */
460    public boolean isEnableJournalDiskSyncs() {
461        return this.letter.isEnableJournalDiskSyncs();
462    }
463
464    /**
465     * Set the enableJournalDiskSyncs
466     *
467     * @deprecated use {@link #setJournalDiskSyncStrategy} instead
468     * @param enableJournalDiskSyncs
469     *            the enableJournalDiskSyncs to set
470     */
471    public void setEnableJournalDiskSyncs(boolean enableJournalDiskSyncs) {
472        this.letter.setEnableJournalDiskSyncs(enableJournalDiskSyncs);
473    }
474
475    /**
476     * @return
477     */
478    public String getJournalDiskSyncStrategy() {
479        return letter.getJournalDiskSyncStrategy();
480    }
481
482    public JournalDiskSyncStrategy getJournalDiskSyncStrategyEnum() {
483        return letter.getJournalDiskSyncStrategyEnum();
484    }
485
486    /**
487     * @param journalDiskSyncStrategy
488     */
489    public void setJournalDiskSyncStrategy(String journalDiskSyncStrategy) {
490        letter.setJournalDiskSyncStrategy(journalDiskSyncStrategy);
491    }
492
493    /**
494     * @return
495     */
496    public long getJournalDiskSyncInterval() {
497        return letter.getJournalDiskSyncInterval();
498    }
499
500    /**
501     * @param journalDiskSyncInterval
502     */
503    public void setJournalDiskSyncInterval(long journalDiskSyncInterval) {
504        letter.setJournalDiskSyncInterval(journalDiskSyncInterval);
505    }
506
507    /**
508     * Get the indexCacheSize
509     *
510     * @return the indexCacheSize
511     */
512    public int getIndexCacheSize() {
513        return this.letter.getIndexCacheSize();
514    }
515
516    /**
517     * Set the indexCacheSize
518     * When set using Xbean, values of the form "20 Mb", "1024kb", and "1g" can be used
519     * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryPropertyEditor"
520     * @param indexCacheSize
521     *            the indexCacheSize to set
522     */
523    public void setIndexCacheSize(int indexCacheSize) {
524        this.letter.setIndexCacheSize(indexCacheSize);
525    }
526
527    /**
528     * Get the ignoreMissingJournalfiles
529     *
530     * @return the ignoreMissingJournalfiles
531     */
532    public boolean isIgnoreMissingJournalfiles() {
533        return this.letter.isIgnoreMissingJournalfiles();
534    }
535
536    /**
537     * Set the ignoreMissingJournalfiles
538     *
539     * @param ignoreMissingJournalfiles
540     *            the ignoreMissingJournalfiles to set
541     */
542    public void setIgnoreMissingJournalfiles(boolean ignoreMissingJournalfiles) {
543        this.letter.setIgnoreMissingJournalfiles(ignoreMissingJournalfiles);
544    }
545
546    public boolean isChecksumJournalFiles() {
547        return letter.isChecksumJournalFiles();
548    }
549
550    public boolean isCheckForCorruptJournalFiles() {
551        return letter.isCheckForCorruptJournalFiles();
552    }
553
554    public void setChecksumJournalFiles(boolean checksumJournalFiles) {
555        letter.setChecksumJournalFiles(checksumJournalFiles);
556    }
557
558    public void setCheckForCorruptJournalFiles(boolean checkForCorruptJournalFiles) {
559        letter.setCheckForCorruptJournalFiles(checkForCorruptJournalFiles);
560    }
561
562    public String getPurgeRecoveredXATransactionStrategy() {
563        return letter.getPurgeRecoveredXATransactionStrategy();
564    }
565
566    public void setPurgeRecoveredXATransactionStrategy(String purgeRecoveredXATransactionStrategy) {
567        letter.setPurgeRecoveredXATransactionStrategy(purgeRecoveredXATransactionStrategy);
568    }
569
570    @Override
571    public void setBrokerService(BrokerService brokerService) {
572        super.setBrokerService(brokerService);
573        letter.setBrokerService(brokerService);
574    }
575
576    public String getPreallocationScope() {
577        return letter.getPreallocationScope();
578    }
579
580    public void setPreallocationScope(String preallocationScope) {
581        this.letter.setPreallocationScope(preallocationScope);
582    }
583
584    public String getPreallocationStrategy() {
585        return letter.getPreallocationStrategy();
586    }
587
588    public void setPreallocationStrategy(String preallocationStrategy) {
589        this.letter.setPreallocationStrategy(preallocationStrategy);
590    }
591
592    public boolean isArchiveDataLogs() {
593        return letter.isArchiveDataLogs();
594    }
595
596    public void setArchiveDataLogs(boolean archiveDataLogs) {
597        letter.setArchiveDataLogs(archiveDataLogs);
598    }
599
600    public File getDirectoryArchive() {
601        return letter.getDirectoryArchive();
602    }
603
604    public void setDirectoryArchive(File directoryArchive) {
605        letter.setDirectoryArchive(directoryArchive);
606    }
607
608    public boolean isConcurrentStoreAndDispatchQueues() {
609        return letter.isConcurrentStoreAndDispatchQueues();
610    }
611
612    public void setConcurrentStoreAndDispatchQueues(boolean concurrentStoreAndDispatch) {
613        letter.setConcurrentStoreAndDispatchQueues(concurrentStoreAndDispatch);
614    }
615
616    public boolean isConcurrentStoreAndDispatchTopics() {
617        return letter.isConcurrentStoreAndDispatchTopics();
618    }
619
620    public void setConcurrentStoreAndDispatchTopics(boolean concurrentStoreAndDispatch) {
621        letter.setConcurrentStoreAndDispatchTopics(concurrentStoreAndDispatch);
622    }
623
624    public int getMaxAsyncJobs() {
625        return letter.getMaxAsyncJobs();
626    }
627    /**
628     * @param maxAsyncJobs
629     *            the maxAsyncJobs to set
630     */
631    public void setMaxAsyncJobs(int maxAsyncJobs) {
632        letter.setMaxAsyncJobs(maxAsyncJobs);
633    }
634
635    /**
636     * @deprecated use {@link Locker#setLockAcquireSleepInterval(long)} instead
637     *
638     * @param databaseLockedWaitDelay the databaseLockedWaitDelay to set
639     */
640    @Deprecated
641    public void setDatabaseLockedWaitDelay(int databaseLockedWaitDelay) throws IOException {
642       getLocker().setLockAcquireSleepInterval(databaseLockedWaitDelay);
643    }
644
645    public boolean getForceRecoverIndex() {
646        return letter.getForceRecoverIndex();
647    }
648
649    public void setForceRecoverIndex(boolean forceRecoverIndex) {
650        letter.setForceRecoverIndex(forceRecoverIndex);
651    }
652
653    public boolean isArchiveCorruptedIndex() {
654        return letter.isArchiveCorruptedIndex();
655    }
656
657    public void setArchiveCorruptedIndex(boolean archiveCorruptedIndex) {
658        letter.setArchiveCorruptedIndex(archiveCorruptedIndex);
659    }
660
661    public float getIndexLFUEvictionFactor() {
662        return letter.getIndexLFUEvictionFactor();
663    }
664
665    public void setIndexLFUEvictionFactor(float indexLFUEvictionFactor) {
666        letter.setIndexLFUEvictionFactor(indexLFUEvictionFactor);
667    }
668
669    public boolean isUseIndexLFRUEviction() {
670        return letter.isUseIndexLFRUEviction();
671    }
672
673    public void setUseIndexLFRUEviction(boolean useIndexLFRUEviction) {
674        letter.setUseIndexLFRUEviction(useIndexLFRUEviction);
675    }
676
677    public void setEnableIndexDiskSyncs(boolean diskSyncs) {
678        letter.setEnableIndexDiskSyncs(diskSyncs);
679    }
680
681    public boolean isEnableIndexDiskSyncs() {
682        return letter.isEnableIndexDiskSyncs();
683    }
684
685    public void setEnableIndexRecoveryFile(boolean enable) {
686        letter.setEnableIndexRecoveryFile(enable);
687    }
688
689    public boolean  isEnableIndexRecoveryFile() {
690        return letter.isEnableIndexRecoveryFile();
691    }
692
693    public void setEnableIndexPageCaching(boolean enable) {
694        letter.setEnableIndexPageCaching(enable);
695    }
696
697    public boolean isEnableIndexPageCaching() {
698        return letter.isEnableIndexPageCaching();
699    }
700
701    public int getCompactAcksAfterNoGC() {
702        return letter.getCompactAcksAfterNoGC();
703    }
704
705    /**
706     * Sets the number of GC cycles where no journal logs were removed before an attempt to
707     * move forward all the acks in the last log that contains them and is otherwise unreferenced.
708     * <p>
709     * A value of -1 will disable this feature.
710     *
711     * @param compactAcksAfterNoGC
712     *      Number of empty GC cycles before we rewrite old ACKS.
713     */
714    public void setCompactAcksAfterNoGC(int compactAcksAfterNoGC) {
715        this.letter.setCompactAcksAfterNoGC(compactAcksAfterNoGC);
716    }
717
718    public boolean isCompactAcksIgnoresStoreGrowth() {
719        return this.letter.isCompactAcksIgnoresStoreGrowth();
720    }
721
722    /**
723     * Configure if Ack compaction will occur regardless of continued growth of the
724     * journal logs meaning that the store has not run out of space yet.  Because the
725     * compaction operation can be costly this value is defaulted to off and the Ack
726     * compaction is only done when it seems that the store cannot grow and larger.
727     *
728     * @param compactAcksIgnoresStoreGrowth the compactAcksIgnoresStoreGrowth to set
729     */
730    public void setCompactAcksIgnoresStoreGrowth(boolean compactAcksIgnoresStoreGrowth) {
731        this.letter.setCompactAcksIgnoresStoreGrowth(compactAcksIgnoresStoreGrowth);
732    }
733
734    /**
735     * Returns whether Ack compaction is enabled
736     *
737     * @return enableAckCompaction
738     */
739    public boolean isEnableAckCompaction() {
740        return letter.isEnableAckCompaction();
741    }
742
743    /**
744     * Configure if the Ack compaction task should be enabled to run
745     *
746     * @param enableAckCompaction
747     */
748    public void setEnableAckCompaction(boolean enableAckCompaction) {
749        letter.setEnableAckCompaction(enableAckCompaction);
750    }
751
752    /**
753     * Whether non-blocking subscription statistics have been enabled
754     *
755     * @return
756     */
757    public boolean isEnableSubscriptionStatistics() {
758        return letter.isEnableSubscriptionStatistics();
759    }
760
761    /**
762     * Enable caching statistics for each subscription to allow non-blocking
763     * retrieval of metrics.  This could incur some overhead to compute if there are a lot
764     * of subscriptions.
765     *
766     * @param enableSubscriptionStatistics
767     */
768    public void setEnableSubscriptionStatistics(boolean enableSubscriptionStatistics) {
769        letter.setEnableSubscriptionStatistics(enableSubscriptionStatistics);
770    }
771
772    public KahaDBStore getStore() {
773        return letter;
774    }
775
776    public KahaTransactionInfo createTransactionInfo(TransactionId txid) {
777        if (txid == null) {
778            return null;
779        }
780        KahaTransactionInfo rc = new KahaTransactionInfo();
781
782        if (txid.isLocalTransaction()) {
783            LocalTransactionId t = (LocalTransactionId) txid;
784            KahaLocalTransactionId kahaTxId = new KahaLocalTransactionId();
785            kahaTxId.setConnectionId(t.getConnectionId().getValue());
786            kahaTxId.setTransactionId(t.getValue());
787            rc.setLocalTransactionId(kahaTxId);
788        } else {
789            XATransactionId t = (XATransactionId) txid;
790            KahaXATransactionId kahaTxId = new KahaXATransactionId();
791            kahaTxId.setBranchQualifier(new Buffer(t.getBranchQualifier()));
792            kahaTxId.setGlobalTransactionId(new Buffer(t.getGlobalTransactionId()));
793            kahaTxId.setFormatId(t.getFormatId());
794            rc.setXaTransactionId(kahaTxId);
795        }
796        return rc;
797    }
798
799    @Override
800    public Locker createDefaultLocker() throws IOException {
801        SharedFileLocker locker = new SharedFileLocker();
802        locker.configure(this);
803        return locker;
804    }
805
806    @Override
807    public void init() throws Exception {}
808
809    @Override
810    public String toString() {
811        String path = getDirectory() != null ? getDirectory().getAbsolutePath() : "DIRECTORY_NOT_SET";
812        return "KahaDBPersistenceAdapter[" + path + (getIndexDirectory() != null ? ",Index:" + getIndexDirectory().getAbsolutePath() : "") +  "]";
813    }
814
815    @Override
816    public void setTransactionIdTransformer(TransactionIdTransformer transactionIdTransformer) {
817        getStore().setTransactionIdTransformer(transactionIdTransformer);
818    }
819
820    @Override
821    public JobSchedulerStore createJobSchedulerStore() throws IOException, UnsupportedOperationException {
822        return this.letter.createJobSchedulerStore();
823    }
824
825    /* (non-Javadoc)
826     * @see org.apache.activemq.store.NoLocalSubscriptionAware#isPersistNoLocal()
827     */
828    @Override
829    public boolean isPersistNoLocal() {
830        return this.letter.isPersistNoLocal();
831    }
832
833    /*
834     * When set, ensure that the cleanup/gc operation is executed during the stop procedure
835     */
836    public void setCleanupOnStop(boolean cleanupOnStop) {
837        this.letter.setCleanupOnStop(cleanupOnStop);
838    }
839
840    public boolean getCleanupOnStop() {
841        return this.letter.getCleanupOnStop();
842    }
843}