]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/cache.c
zap charray
[openldap] / servers / slapd / back-bdb / cache.c
index 35d5a5720dc1fba8f9a7a7cdae082c8b40ab0614..961c047e2bf5bac87f9a6ca3987c265196f22dc0 100644 (file)
@@ -49,9 +49,9 @@ static int
 bdb_cache_entry_rdwr_lock(Entry *e, int rw)
 {
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
-                  "bdb_cache_entry_rdwr_lock: %s lock on ID %ld\n",
-                  rw ? "w" : "r", e->e_id ));
+       LDAP_LOG( CACHE, ENTRY, 
+               "bdb_cache_entry_rdwr_lock: %s lock on ID %ld\n",
+               rw ? "w" : "r", e->e_id, 0 );
 #else
        Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n",
                rw ? "w" : "r", e->e_id, 0);
@@ -67,9 +67,9 @@ static int
 bdb_cache_entry_rdwr_trylock(Entry *e, int rw)
 {
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
-                  "bdb_cache_entry_rdwr_trylock: try %s lock on ID: %ld.\n",
-                  rw ? "w" : "r", e->e_id ));
+       LDAP_LOG( CACHE, ENTRY, 
+               "bdb_cache_entry_rdwr_trylock: try %s lock on ID: %ld.\n",
+               rw ? "w" : "r", e->e_id, 0 );
 #else
        Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n",
                rw ? "w" : "r", e->e_id, 0);
@@ -85,9 +85,9 @@ static int
 bdb_cache_entry_rdwr_unlock(Entry *e, int rw)
 {
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
-                  "bdb_cache_entry_rdwr_unlock: remove %s lock on ID %ld.\n",
-                  rw ? "w" : "r", e->e_id ));
+       LDAP_LOG( CACHE, ENTRY, 
+               "bdb_cache_entry_rdwr_unlock: remove %s lock on ID %ld.\n",
+               rw ? "w" : "r", e->e_id, 0 );
 #else
        Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n",
                rw ? "w" : "r", e->e_id, 0);
@@ -149,6 +149,17 @@ bdb_cache_entry_db_lock
        lockobj.size = e->e_nname.bv_len;
        rc = LOCK_GET(env, locker, flags | DB_LOCK_NOWAIT,
                                        &lockobj, db_rw, lock);
+       if (rc) {
+#ifdef NEW_LOGGING
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_entry_db_lock: entry %s, rw %d, rc %d\n",
+                       e->e_nname.bv_val, rw, rc );
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_cache_entry_db_lock: entry %s, rw %d, rc %d\n",
+                       e->e_nname.bv_val, rw, rc );
+#endif
+       }
        return rc;
 }
 
@@ -232,12 +243,12 @@ bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
                ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
-                          id, rw ? "w" : "r", refcnt ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                          "bdb_unlocked_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
+                          id, rw ? "w" : "r", refcnt );
 #else
                Debug( LDAP_DEBUG_TRACE,
-                       "====> bdb_cache_return_entry_%s( %ld ): created (%d)\n",
+                       "====> bdb_unlocked_cache_return_entry_%s( %ld ): created (%d)\n",
                        rw ? "w" : "r", id, refcnt );
 #endif
 
@@ -248,12 +259,12 @@ bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
                        ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                                  "bdb_cache_return_entry_rw: %ld, delete pending (%d).\n",
-                                  id, refcnt ));
+                       LDAP_LOG( CACHE, DETAIL1, 
+                                  "bdb_unlocked_cache_return_entry_rw: %ld, delete pending (%d).\n",
+                                  id, refcnt, 0 );
 #else
                        Debug( LDAP_DEBUG_TRACE,
-                               "====> bdb_cache_return_entry_%s( %ld ): delete pending (%d)\n",
+                               "====> bdb_unlocked_cache_return_entry_%s( %ld ): delete pending (%d)\n",
                                rw ? "w" : "r", id, refcnt );
 #endif
 
@@ -267,12 +278,12 @@ bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
                        ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                                  "bdb_cache_return_entry_rw: (%ld): deleted (%d)\n",
-                                  id, refcnt ));
+                       LDAP_LOG( CACHE, DETAIL1, 
+                                  "bdb_unlocked_cache_return_entry_rw: (%ld): deleted (%d)\n",
+                                  id, refcnt, 0 );
 #else
                        Debug( LDAP_DEBUG_TRACE,
-                               "====> bdb_cache_return_entry_%s( %ld ): deleted (%d)\n",
+                               "====> bdb_unlocked_cache_return_entry_%s( %ld ): deleted (%d)\n",
                                rw ? "w" : "r", id, refcnt );
 #endif
                }
@@ -282,12 +293,12 @@ bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
                ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
-                          id, rw ? "w": "r", refcnt ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                          "bdb_unlocked_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
+                          id, rw ? "w": "r", refcnt );
 #else
                Debug( LDAP_DEBUG_TRACE,
-                       "====> bdb_cache_return_entry_%s( %ld ): returned (%d)\n",
+                       "====> bdb_unlocked_cache_return_entry_%s( %ld ): returned (%d)\n",
                        rw ? "w" : "r", id, refcnt);
 #endif
        }
@@ -335,9 +346,9 @@ bdb_cache_return_entry_rw
                ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+               LDAP_LOG( CACHE, DETAIL1, 
                           "bdb_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
-                          id, rw ? "w" : "r", refcnt ));
+                          id, rw ? "w" : "r", refcnt );
 #else
                Debug( LDAP_DEBUG_TRACE,
                        "====> bdb_cache_return_entry_%s( %ld ): created (%d)\n",
@@ -351,9 +362,9 @@ bdb_cache_return_entry_rw
                        ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                       LDAP_LOG( CACHE, DETAIL1, 
                                   "bdb_cache_return_entry_rw: %ld, delete pending (%d).\n",
-                                  id, refcnt ));
+                                  id, refcnt, 0 );
 #else
                        Debug( LDAP_DEBUG_TRACE,
                                "====> bdb_cache_return_entry_%s( %ld ): delete pending (%d)\n",
@@ -370,9 +381,9 @@ bdb_cache_return_entry_rw
                        ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+                       LDAP_LOG( CACHE, DETAIL1, 
                                   "bdb_cache_return_entry_rw: (%ld): deleted (%d)\n",
-                                  id, refcnt ));
+                                  id, refcnt, 0 );
 #else
                        Debug( LDAP_DEBUG_TRACE,
                                "====> bdb_cache_return_entry_%s( %ld ): deleted (%d)\n",
@@ -385,9 +396,9 @@ bdb_cache_return_entry_rw
                ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+               LDAP_LOG( CACHE, DETAIL1, 
                           "bdb_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
-                          id, rw ? "w": "r", refcnt ));
+                          id, rw ? "w": "r", refcnt );
 #else
                Debug( LDAP_DEBUG_TRACE,
                        "====> bdb_cache_return_entry_%s( %ld ): returned (%d)\n",
@@ -442,9 +453,9 @@ bdb_cache_add_entry_rw(
        Entry   *ee;
 
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
-                  "bdb_cache_add_entry_rw: add (%s):%s to cache\n",
-                  e->e_dn, rw ? "w" : "r" ));
+       LDAP_LOG( CACHE, ENTRY, 
+               "bdb_cache_add_entry_rw: add (%s):%s to cache\n",
+               e->e_dn, rw ? "w" : "r", 0 );
 #endif
        /* set cache write lock */
        ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
@@ -456,9 +467,9 @@ bdb_cache_add_entry_rw(
                ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_ERR,
-                          "bdb_cache_add_entry_rw: add (%s):%ld private init failed!\n",
-                          e->e_dn, e->e_id ));
+               LDAP_LOG( CACHE, ERR, 
+                       "bdb_cache_add_entry_rw: add (%s):%ld private init failed!\n",
+                       e->e_dn, e->e_id, 0 );
 #else
                Debug( LDAP_DEBUG_ANY,
                        "====> bdb_cache_add_entry( %ld ): \"%s\": private init failed!\n",
@@ -476,9 +487,9 @@ bdb_cache_add_entry_rw(
                ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_add_entry: (%s):%ld already in cache.\n",
-                          e->e_dn, e->e_id ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_add_entry: (%s):%ld already in cache.\n",
+                       e->e_dn, e->e_id, 0 );
 #else
                Debug( LDAP_DEBUG_TRACE,
                        "====> bdb_cache_add_entry( %ld ): \"%s\": already in dn cache\n",
@@ -495,9 +506,9 @@ bdb_cache_add_entry_rw(
                (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 )
        {
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_add_entry: (%s):%ls already in cache.\n",
-                          e->e_dn, e->e_id ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_add_entry: (%s):%ls already in cache.\n",
+                       e->e_dn, e->e_id, 0 );
 #else
                Debug( LDAP_DEBUG_ANY,
                        "====> bdb_cache_add_entry( %ld ): \"%s\": already in id cache\n",
@@ -509,9 +520,9 @@ bdb_cache_add_entry_rw(
                        (AVL_CMP) entry_dn_cmp ) == NULL )
                {
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                                  "bdb_cache_add_entry: can't delete (%s) from cache.\n",
-                                  e->e_dn ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_add_entry: can't delete (%s) from cache.\n", 
+                               e->e_dn, 0, 0 );
 #else
                        Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
                            0, 0, 0 );
@@ -535,8 +546,9 @@ bdb_cache_add_entry_rw(
                if ( avl_delete( &cache->c_idtree, (caddr_t) e,
                        (AVL_CMP) entry_id_cmp ) == NULL ) {
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                               "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_add_entry: can't delete (%s) from cache.\n", 
+                               e->e_dn, 0, 0 );
 #else
                        Debug( LDAP_DEBUG_ANY, "====> can't delete from id cache\n", 0, 0, 0 );
 #endif
@@ -544,8 +556,9 @@ bdb_cache_add_entry_rw(
                if ( avl_delete( &cache->c_dntree, (caddr_t) e,
                                (AVL_CMP) entry_dn_cmp ) == NULL ) {
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                                       "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_add_entry: can't delete (%s) from cache.\n", 
+                               e->e_dn, 0, 0 );
 #else
                        Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", 0, 0, 0 );
 #endif
@@ -633,9 +646,9 @@ bdb_cache_update_entry(
                (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 )
        {
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_update_entry: (%s):%ld already in dn cache\n",
-                          e->e_dn, e->e_id ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_update_entry: (%s):%ld already in dn cache\n",
+                       e->e_dn, e->e_id, 0 );
 #else
                Debug( LDAP_DEBUG_TRACE,
                        "====> bdb_cache_update_entry( %ld ): \"%s\": already in dn cache\n",
@@ -652,9 +665,9 @@ bdb_cache_update_entry(
                (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 )
        {
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_update_entry: (%s)%ld already in id cache\n",
-                          e->e_dn, e->e_id ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_update_entry: (%s)%ld already in id cache\n",
+                       e->e_dn, e->e_id, 0 );
 #else
                Debug( LDAP_DEBUG_ANY,
                        "====> bdb_cache_update_entry( %ld ): \"%s\": already in id cache\n",
@@ -666,9 +679,9 @@ bdb_cache_update_entry(
                        (AVL_CMP) entry_dn_cmp ) == NULL )
                {
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                                  "bdb_cache_update_entry: can't delete (%s)%ld from dn cache.\n",
-                                  e->e_dn, e->e_id ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_update_entry: can't delete (%s)%ld from dn cache.\n",
+                               e->e_dn, e->e_id, 0 );
 #else
                        Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n",
                            0, 0, 0 );
@@ -778,9 +791,9 @@ try_again:
                        ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                                  "bdb_cache_find_entry_dn2id: (%s) %ld not ready: %d\n",
-                                  ndn->bv_val, id, state ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_find_entry_dn2id: (%s) %ld not ready: %d\n",
+                               ndn->bv_val, id, state );
 #else
                        Debug(LDAP_DEBUG_TRACE,
                                "====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n",
@@ -806,9 +819,9 @@ try_again:
                ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_find_entry_dn2id: (%s): %ld %d tries\n",
-                          ndn->bv_val, id, count ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_find_entry_dn2id: (%s): %ld %d tries\n",
+                       ndn->bv_val, id, count );
 #else
                Debug(LDAP_DEBUG_TRACE,
                        "====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n",
@@ -874,9 +887,9 @@ try_again:
                        ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                                  "bdb_cache_find_entry_id: (%ld)->%ld not ready (%d).\n",
-                                  id, ep_id, state ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_find_entry_id: (%ld)->%ld not ready (%d).\n",
+                               id, ep_id, state );
                                   
 #else
                        Debug(LDAP_DEBUG_TRACE,
@@ -905,9 +918,9 @@ try_again:
                        ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock );
 
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                                  "bdb_cache_find_entry_id: %ld -> %ld (busy) %d.\n",
-                                  id, ep_id, state ));
+                       LDAP_LOG( CACHE, INFO, 
+                               "bdb_cache_find_entry_id: %ld -> %ld (busy) %d.\n",
+                               id, ep_id, state );
 #else
                        Debug(LDAP_DEBUG_TRACE,
                                "====> bdb_cache_find_entry_id( %ld ): %ld (busy) %d\n",
@@ -935,9 +948,9 @@ try_again:
                ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
 
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
-                          "bdb_cache_find_entry_id: %ld -> %s  found %d tries.\n",
-                          ep_id, ep->e_dn, count ));
+               LDAP_LOG( CACHE, DETAIL1, 
+                       "bdb_cache_find_entry_id: %ld -> %s  found %d tries.\n",
+                       ep_id, ep->e_dn, count );
 #else
                Debug(LDAP_DEBUG_TRACE,
                        "====> bdb_cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n",
@@ -979,8 +992,8 @@ bdb_cache_delete_entry(
        assert( e->e_private );
 
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
-                  "bdb_cache_delete_entry: delete %ld.\n", e->e_id ));
+       LDAP_LOG( CACHE, ENTRY, 
+               "bdb_cache_delete_entry: delete %ld.\n", e->e_id, 0, 0 );
 #else
        Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_delete_entry( %ld )\n",
                e->e_id, 0, 0 );
@@ -1047,8 +1060,7 @@ bdb_cache_release_all( Cache *cache )
        ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
 
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY,
-                  "bdb_cache_release_all: enter\n" ));
+       LDAP_LOG( CACHE, ENTRY, "bdb_cache_release_all: enter\n", 0, 0, 0 );
 #else
        Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_release_all\n", 0, 0, 0 );
 #endif
@@ -1067,8 +1079,8 @@ bdb_cache_release_all( Cache *cache )
 
        if ( cache->c_cursize ) {
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
-                          "bdb_cache_release_all: Entry cache could not be emptied.\n" ));
+               LDAP_LOG( CACHE, INFO,
+                  "bdb_cache_release_all: Entry cache could not be emptied.\n", 0, 0, 0 );
 #else
                Debug( LDAP_DEBUG_TRACE, "Entry-cache could not be emptied\n", 0, 0, 0 );
 #endif
@@ -1099,3 +1111,57 @@ bdb_lru_print( Cache *cache )
        }
 }
 #endif
+
+#ifdef BDB_REUSE_LOCKERS
+void
+bdb_locker_id_free( void *key, void *data )
+{
+       DB_ENV *env = key;
+       int lockid = (int) data;
+
+       XLOCK_ID_FREE( env, lockid );
+}
+
+int
+bdb_locker_id( Operation *op, DB_ENV *env, int *locker )
+{
+       int i, rc, lockid;
+       void *data;
+
+       if ( !env || !op || !locker ) return -1;
+
+       /* Shouldn't happen unless we're single-threaded */
+       if ( !op->o_threadctx ) {
+               *locker = 0;
+               return 0;
+       }
+
+       if ( ldap_pvt_thread_pool_getkey( op->o_threadctx, env, &data, NULL ) ) {
+               for ( i=0, rc=1; rc != 0 && i<4; i++ ) {
+                       rc = XLOCK_ID( env, &lockid );
+                       if (rc) ldap_pvt_thread_yield();
+               }
+               if ( rc != 0) {
+                       return rc;
+               }
+               data = (void *)lockid;
+               if ( ( rc = ldap_pvt_thread_pool_setkey( op->o_threadctx, env,
+                       data, bdb_locker_id_free ) ) ) {
+                       XLOCK_ID_FREE( env, lockid );
+#ifdef NEW_LOGGING
+                       LDAP_LOG( BACK_BDB, ERR, "bdb_locker_id: err %s(%d)\n",
+                               db_strerror(rc), rc, 0 );
+#else
+                       Debug( LDAP_DEBUG_ANY, "bdb_locker_id: err %s(%d)\n",
+                               db_strerror(rc), rc, 0 );
+#endif
+
+                       return rc;
+               }
+       } else {
+               lockid = (int)data;
+       }
+       *locker = lockid;
+       return 0;
+}
+#endif