You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zy...@apache.org on 2011/06/28 11:17:59 UTC

svn commit: r1140493 - in /trafficserver/traffic/branches/ssd: ./ iocore/cache/ lib/ts/ mgmt/ mgmt/cli/ proxy/config/ proxy/http/

Author: zym
Date: Tue Jun 28 09:17:58 2011
New Revision: 1140493

URL: http://svn.apache.org/viewvc?rev=1140493&view=rev
Log:
TS-745 add SSD layer in the disk storages

Author: Zhang Lian <mo...@taobao.com>

This is the first full tested patch that implement the ssd storage
that is working in simple way. There will be a storage_ssd.config
with the same syntax as storage.config, when enable, the SSD codes
will take into action.
Please take TS-745 as full reference.

Added:
    trafficserver/traffic/branches/ssd/proxy/config/storage_ssd.config.default.in
Modified:
    trafficserver/traffic/branches/ssd/configure.ac
    trafficserver/traffic/branches/ssd/iocore/cache/Cache.cc
    trafficserver/traffic/branches/ssd/iocore/cache/CacheDir.cc
    trafficserver/traffic/branches/ssd/iocore/cache/CacheHosting.cc
    trafficserver/traffic/branches/ssd/iocore/cache/CacheRead.cc
    trafficserver/traffic/branches/ssd/iocore/cache/CacheWrite.cc
    trafficserver/traffic/branches/ssd/iocore/cache/I_Cache.h
    trafficserver/traffic/branches/ssd/iocore/cache/P_CacheDisk.h
    trafficserver/traffic/branches/ssd/iocore/cache/P_CacheHosting.h
    trafficserver/traffic/branches/ssd/iocore/cache/P_CacheInternal.h
    trafficserver/traffic/branches/ssd/lib/ts/ink_config.h.in
    trafficserver/traffic/branches/ssd/mgmt/AddConfigFilesHere.cc
    trafficserver/traffic/branches/ssd/mgmt/RecordsConfig.cc
    trafficserver/traffic/branches/ssd/mgmt/cli/ShowCmd.cc
    trafficserver/traffic/branches/ssd/proxy/config/Makefile.am
    trafficserver/traffic/branches/ssd/proxy/http/HttpCacheSM.cc
    trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.cc
    trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.h
    trafficserver/traffic/branches/ssd/proxy/http/HttpSM.cc
    trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.cc
    trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.h

Modified: trafficserver/traffic/branches/ssd/configure.ac
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/configure.ac?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/configure.ac (original)
+++ trafficserver/traffic/branches/ssd/configure.ac Tue Jun 28 09:17:58 2011
@@ -766,7 +766,7 @@ case $host_os in
     TCL_LIB_SPEC="-ltcl" # OSX fails to populate this variable
     ;;
   *)
-   ;;
+    ;;
 esac
 AC_SUBST([LIBTCL],[$TCL_LIB_SPEC])
 
@@ -1202,7 +1202,8 @@ AC_CONFIG_FILES([lib/tsconfig/Makefile])
 AC_CONFIG_FILES([Makefile])
 AC_CONFIG_FILES([proxy/config/body_factory/default/Makefile])
 AC_CONFIG_FILES([proxy/config/body_factory/Makefile])
-AC_CONFIG_FILES([proxy/config/records.config.default proxy/config/storage.config.default])
+AC_CONFIG_FILES([proxy/config/records.config.default
+		proxy/config/storage_ssd.config.default proxy/config/storage.config.default])
 AC_CONFIG_FILES([proxy/config/Makefile])
 AC_CONFIG_FILES([proxy/congest/Makefile])
 AC_CONFIG_FILES([proxy/hdrs/Makefile])

Modified: trafficserver/traffic/branches/ssd/iocore/cache/Cache.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/Cache.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/Cache.cc (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/Cache.cc Tue Jun 28 09:17:58 2011
@@ -78,6 +78,10 @@ int cache_config_read_while_writer = 0;
 char cache_system_config_directory[PATH_NAME_MAX + 1];
 int cache_config_mutex_retry_delay = 2;
 
+#ifdef CACHE_SSD
+Store ssd_store;
+#endif
+
 // Globals
 
 RecRawStatBlock *cache_rsb = NULL;
@@ -581,6 +585,9 @@ CacheProcessor::start_internal(int flags
         }
         off_t skip = ROUND_TO_STORE_BLOCK((sd->offset < START_POS ? START_POS + sd->alignment : sd->offset));
         blocks = blocks - ROUND_TO_STORE_BLOCK(sd->offset + skip);
+#ifdef CACHE_SSD
+        gdisks[gndisks]->is_ssd = false;
+#endif
         gdisks[gndisks]->open(path, blocks, skip, sector_size, fd, clear);
         gndisks++;
       }
@@ -592,6 +599,57 @@ CacheProcessor::start_internal(int flags
     Warning("unable to open cache disk(s): Cache Disabled\n");
     return -1;
   }
+
+#ifdef CACHE_SSD
+  diskok = 1;
+  sd = NULL;
+  for (i = 0; i < ssd_store.n_disks; ++i) {
+    sd = ssd_store.disk[i];
+    char path[PATH_MAX];
+    int opts = O_RDWR;
+    ink_strlcpy(path, sd->pathname, sizeof(path));
+    if (!sd->file_pathname) {
+      ink_strlcat(path, "/ssd_cache.db", sizeof(path));
+      opts |= O_CREAT;
+    }
+    opts |= _O_ATTRIB_OVERLAPPED;
+#ifdef O_DIRECT
+    opts |= O_DIRECT;
+#endif
+#ifdef O_DSYNC
+    opts |= O_DSYNC;
+#endif
+
+    int fd = open(path, opts, 0644);
+    int blocks = sd->blocks;
+    if (fd > 0) {
+      if (!sd->file_pathname) {
+        if (ftruncate(fd, ((uint64_t) blocks) * STORE_BLOCK_SIZE) < 0) {
+          Warning("unable to truncate cache file '%s' to %d blocks", path, blocks);
+          diskok = 0;
+        }
+      }
+      if (diskok) {
+        gdisks[gndisks] = NEW(new CacheDisk());
+        Debug("cache_hosting", "Disk: %d, blocks: %d", gndisks, blocks);
+        int sector_size = sd->hw_sector_size;
+        if (sector_size < cache_config_force_sector_size)
+          sector_size = cache_config_force_sector_size;
+        if (sd->hw_sector_size <= 0 || sector_size > STORE_BLOCK_SIZE) {
+          Warning("bad hardware sector size %d, resetting to %d", sector_size, STORE_BLOCK_SIZE);
+          sector_size = STORE_BLOCK_SIZE;
+        }
+        off_t skip = ROUND_TO_STORE_BLOCK((sd->offset < START_POS ? START_POS + sd->alignment : sd->offset));
+        blocks = blocks - ROUND_TO_STORE_BLOCK(sd->offset + skip);
+        gdisks[gndisks]->is_ssd = true;
+        gdisks[gndisks]->open(path, blocks, skip, sector_size, fd, clear);
+        gndisks++;
+      }
+    } else
+      Warning("unable to open '%s': %s", path, strerror(errno));
+  }
+
+#endif
   start_done = 1;
 
   return 0;
@@ -792,7 +850,6 @@ CacheProcessor::cacheInitialized()
           total_cache_bytes += vol_total_cache_bytes;
           Debug("cache_init", "CacheProcessor::cacheInitialized - total_cache_bytes = %" PRId64 " = %" PRId64 "Mb",
                 total_cache_bytes, total_cache_bytes / (1024 * 1024));
-
           CACHE_VOL_SUM_DYN_STAT(cache_bytes_total_stat, vol_total_cache_bytes);
 
 
@@ -845,7 +902,6 @@ CacheProcessor::cacheInitialized()
           CACHE_VOL_SUM_DYN_STAT(cache_bytes_total_stat, vol_total_cache_bytes);
           Debug("cache_init", "CacheProcessor::cacheInitialized - total_cache_bytes = %" PRId64 " = %" PRId64 "Mb",
                 total_cache_bytes, total_cache_bytes / (1024 * 1024));
-
           vol_total_direntries = gvol[i]->buckets * gvol[i]->segments * DIR_DEPTH;
           total_direntries += vol_total_direntries;
           CACHE_VOL_SUM_DYN_STAT(cache_direntries_total_stat, vol_total_direntries);
@@ -1747,10 +1803,22 @@ Cache::open_done()
   hosttable = NEW(new CacheHostTable(this, scheme));
   hosttable->register_config_callback(&hosttable);
 
+#ifdef CACHE_SSD
+  if (0 != ssd_store.n_disks) {
+    ssd_hosttable = NEW(new CacheHostTable(this, scheme, true));
+    ssd_hosttable->register_config_callback(&ssd_hosttable);
+  }
+#endif
+
   if (hosttable->gen_host_rec.num_cachevols == 0)
     ready = CACHE_INIT_FAILED;
   else
     ready = CACHE_INITIALIZED;
+
+#ifdef CACHE_SSD
+  if (ready == CACHE_INITIALIZED && 0 != ssd_store.n_disks && ssd_hosttable->gen_host_rec.num_cachevols == 0)
+    ready = CACHE_INIT_FAILED;
+#endif
   cacheProcessor.cacheInitialized();
 
   return 0;
@@ -1898,14 +1966,27 @@ CacheVC::handleReadDone(int event, Event
           okay = 0;
         }
       }
+#ifdef CACHE_SSD
+      // copy doc before unmarshal
+      if (vol_backup != NULL && okay && !f.doc_from_ssd && !f.doc_from_ram_cache && !f.remove && !f.read_before_write) {
+        if (write2ssd_doc != NULL) {
+          xfree(write2ssd_doc);
+          write2ssd_doc = NULL;
+        }
+        write2ssd_len = doc->len;
+        write2ssd_doc = (char *)xmalloc(doc->len);
+        memcpy(write2ssd_doc, doc, doc->len);
+      }
+#endif
       bool http_copy_hdr = false;
 #ifdef HTTP_CACHE
       http_copy_hdr = cache_config_ram_cache_compress && !f.doc_from_ram_cache &&
         doc->ftype == CACHE_FRAG_TYPE_HTTP && doc->hlen;
       // If http doc we need to unmarshal the headers before putting in the ram cache
       // unless it could be compressed
-      if (!http_copy_hdr && doc->ftype == CACHE_FRAG_TYPE_HTTP && doc->hlen && okay)
+      if (!http_copy_hdr && doc->ftype == CACHE_FRAG_TYPE_HTTP && doc->hlen && okay) {
         unmarshal_helper(doc, buf, okay);
+      }
 #endif
       // Put the request in the ram cache only if its a open_read or lookup
       if (vio.op == VIO::READ && okay) {
@@ -1919,9 +2000,12 @@ CacheVC::handleReadDone(int event, Event
         cutoff_check = ((!doc_len && (int64_t)doc->total_len < cache_config_ram_cache_cutoff)
                         || (doc_len && (int64_t)doc_len < cache_config_ram_cache_cutoff)
                         || !cache_config_ram_cache_cutoff);
-        if (cutoff_check && !f.doc_from_ram_cache) {
+        if (cutoff_check && !f.doc_from_ram_cache && !f.remove) {
           uint64_t o = dir_offset(&dir);
           vol->ram_cache->put(read_key, buf, doc->len, http_copy_hdr, (uint32_t)(o >> 32), (uint32_t)o);
+#ifdef CACHE_SSD
+          f.write_to_ramcache = true;
+#endif
         }
         if (!doc_len) {
           // keep a pointer to it. In case the state machine decides to
@@ -2123,6 +2207,71 @@ Lfree:
   return free_CacheVC(this);
 }
 
+#ifdef CACHE_SSD
+int
+CacheVC::removeSSD(int event, Event *e)
+{
+  NOWARN_UNUSED(e);
+  NOWARN_UNUSED(event);
+
+  cancel_trigger();
+  set_io_not_in_progress();
+  {
+    MUTEX_TRY_LOCK(lock, vol->mutex, mutex->thread_holding);
+    if (!lock) {
+      Debug("ssd_cache_trylock", "trylock ssd fail in removeSSD");
+      VC_SCHED_LOCK_RETRY();
+    }
+    if (_action.cancelled) {
+      goto Lfree;
+    }
+  Lread:
+    if (!buf)
+      goto Lcollision;
+    if (!dir_valid(vol, &dir)) {
+      last_collision = NULL;
+      goto Lcollision;
+    }
+    // check read completed correct FIXME: remove bad vols
+    if ((int) io.aio_result != (int) io.aiocb.aio_nbytes)
+      goto Ldone;
+    {
+      // verify that this is our document
+      Doc *doc = (Doc *) buf->data();
+      /* should be first_key not key..right?? */
+      if (doc->first_key == key) {
+        ink_assert(doc->magic == DOC_MAGIC);
+        if (dir_delete(&key, vol, &dir) > 0) {
+          goto Lremoved;
+        }
+        goto Ldone;
+      }
+    }
+  Lcollision:
+    // check for collision
+    if (dir_probe(&key, vol, &dir, &last_collision) > 0) {
+      Debug("ssd_cache_remove", "probe hit in ssd, and read");
+      int ret = do_read_call(&key);
+      if (ret == EVENT_RETURN)
+        goto Lread;
+      return ret;
+    } else {
+      Debug("ssd_cache_remove", "The object is not in ssd");
+      goto Lremoved;
+    }
+  Ldone:
+    CACHE_INCREMENT_DYN_STAT(cache_remove_failure_stat);
+  }
+  ink_debug_assert(!vol || this_ethread() != vol->mutex->thread_holding);
+  _action.continuation->handleEvent(CACHE_EVENT_REMOVE_FAILED, (void *) -ECACHE_NO_DOC);
+  goto Lfree;
+Lremoved:
+  _action.continuation->handleEvent(CACHE_EVENT_REMOVE, 0);
+Lfree:
+  return free_CacheVC(this);
+}
+#endif
+
 Action *
 Cache::remove(Continuation *cont, CacheKey *key, CacheFragType type,
               bool user_agents, bool link,
@@ -2139,6 +2288,35 @@ Cache::remove(Continuation *cont, CacheK
 
   ink_assert(this);
 
+#ifdef CACHE_SSD
+  Vol *ssd_vol = key_to_vol(key, hostname, host_len, true);
+  if (ssd_vol != NULL)
+  {
+    Continuation *remove_ssd = new_CacheRemoveCont();
+    CACHE_TRY_LOCK(lock, remove_ssd->mutex, this_ethread());
+    ink_assert(lock);
+    Vol *vol = ssd_vol;
+    // coverity[var_decl]
+    Dir result;
+    dir_clear(&result);           // initialized here, set result empty so we can recognize missed lock
+    ProxyMutexPtr mutex = remove_ssd->mutex;
+
+    CacheVC *c = new_CacheVC(remove_ssd);
+    c->vio.op = VIO::NONE;
+    c->frag_type = type;
+    c->base_stat = cache_remove_active_stat;
+    CACHE_INCREMENT_DYN_STAT(c->base_stat + CACHE_STAT_ACTIVE);
+    c->first_key = c->key = *key;
+    c->vol = ssd_vol;
+    c->dir = result;
+    c->f.remove = 1;
+
+    SET_CONTINUATION_HANDLER(c, &CacheVC::removeSSD);
+    int ret = c->removeSSD(EVENT_IMMEDIATE, 0);
+    Debug("ssd_cache_remove", "%d\n", ret);
+  }
+#endif
+
   ProxyMutexPtr mutex = NULL;
   if (!cont)
     cont = new_CacheRemoveCont();
@@ -2284,15 +2462,15 @@ cplist_reconfigure()
         gdisks[i]->delete_all_volumes();
       }
       if (gdisks[i]->cleared) {
-        uint64_t free_space = gdisks[i]->free_space * STORE_BLOCK_SIZE;
-        int vols = (free_space / MAX_VOL_SIZE) + 1;
-        for (int p = 0; p < vols; p++) {
-          off_t b = gdisks[i]->free_space / (vols - p);
-          Debug("cache_hosting", "blocks = %d\n", b);
-          DiskVolBlock *dpb = gdisks[i]->create_volume(0, b, CACHE_HTTP_TYPE);
-          ink_assert(dpb && dpb->len == (uint64_t)b);
-        }
-        ink_assert(gdisks[i]->free_space == 0);
+          uint64_t free_space = gdisks[i]->free_space * STORE_BLOCK_SIZE;
+          int vols = (free_space / MAX_VOL_SIZE) + 1; 
+          for (int p = 0; p < vols; ++p) {
+            off_t b = gdisks[i]->free_space / (vols - p);
+            Debug("cache_hosting", "blocks = %d\n", b);
+            DiskVolBlock *dpb = gdisks[i]->create_volume(0, b, CACHE_HTTP_TYPE);
+            ink_assert(dpb && dpb->len == (uint64_t)b);
+          }
+          ink_assert(gdisks[i]->free_space == 0);
       }
 
       ink_assert(gdisks[i]->header->num_volumes == 1);
@@ -2537,8 +2715,46 @@ rebuild_host_table(Cache *cache)
 
 // if generic_host_rec.vols == NULL, what do we do???
 Vol *
-Cache::key_to_vol(CacheKey *key, char *hostname, int host_len)
-{
+Cache::key_to_vol(CacheKey *key, char *hostname, int host_len
+#ifdef CACHE_SSD
+    , int ssd_type
+#endif
+    )
+{
+#ifdef CACHE_SSD
+  if (ssd_type) {
+    if (0 == ssd_store.n_disks)
+      return NULL;
+    uint32_t h = (key->word(2) >> DIR_TAG_WIDTH) % VOL_HASH_TABLE_SIZE;
+    unsigned short *hash_table = ssd_hosttable->gen_host_rec.vol_hash_table;
+    CacheHostRecord *host_rec = &ssd_hosttable->gen_host_rec;
+
+    if (ssd_hosttable->m_numEntries > 0 && host_len) {
+      CacheHostResult res;
+      ssd_hosttable->Match(hostname, host_len, &res);
+      if (res.record) {
+        unsigned short *host_hash_table = res.record->vol_hash_table;
+        if (host_hash_table) {
+          if (is_debug_tag_set("ssd_cache_hosting")) {
+            char format_str[50];
+            snprintf(format_str, sizeof(format_str), "Volume: %%xd for host: %%.%ds", host_len);
+            Debug("ssd_cache_hosting", format_str, res.record, hostname);
+          }
+          return res.record->vols[host_hash_table[h]];
+        }
+      }
+    }
+    if (hash_table) {
+      if (is_debug_tag_set("ssd_cache_hosting")) {
+        char format_str[50];
+        snprintf(format_str, sizeof(format_str), "Generic volume: %%xd for host: %%.%ds", host_len);
+        Debug("ssd_cache_hosting", format_str, host_rec, hostname);
+      }
+      return host_rec->vols[hash_table[h]];
+    } else
+      return host_rec->vols[0];
+  } else {
+#endif
   uint32_t h = (key->word(2) >> DIR_TAG_WIDTH) % VOL_HASH_TABLE_SIZE;
   unsigned short *hash_table = hosttable->gen_host_rec.vol_hash_table;
   CacheHostRecord *host_rec = &hosttable->gen_host_rec;
@@ -2567,6 +2783,9 @@ Cache::key_to_vol(CacheKey *key, char *h
     return host_rec->vols[hash_table[h]];
   } else
     return host_rec->vols[0];
+#ifdef CACHE_SSD
+  }
+#endif
 }
 
 static void reg_int(const char *str, int stat, RecRawStatBlock *rsb, const char *prefix, RecRawStatSyncCb sync_cb=RecRawStatSyncSum) {
@@ -2599,6 +2818,11 @@ register_cache_stats(RecRawStatBlock *rs
   REG_INT("read.active", cache_read_active_stat);
   REG_INT("read.success", cache_read_success_stat);
   REG_INT("read.failure", cache_read_failure_stat);
+#ifdef CACHE_SSD
+  REG_INT("ssd.read.active", cache_ssd_read_active_stat);
+  REG_INT("ssd.read.success", cache_ssd_read_success_stat);
+  REG_INT("ssd.read.failure", cache_ssd_read_failure_stat);
+#endif
   REG_INT("write.active", cache_write_active_stat);
   REG_INT("write.success", cache_write_success_stat);
   REG_INT("write.failure", cache_write_failure_stat);
@@ -2754,6 +2978,22 @@ ink_cache_init(ModuleVersion v)
     Warning("no cache disks specified in %s: cache disabled\n", p);
     //exit(1);
   }
+
+#ifdef CACHE_SSD
+  char ssd_path[PATH_NAME_MAX + 1];
+  char ssd_file[PATH_NAME_MAX + 1];
+  IOCORE_ReadConfigString(ssd_file, "proxy.config.cache.ssd_filename", PATH_NAME_MAX);
+  Layout::relative_to(ssd_path, PATH_NAME_MAX, Layout::get()->sysconfdir, ssd_file);
+  int ssd_fd = ::open(ssd_path, O_RDONLY);
+  if(ssd_fd < 0) {
+    Error("fail on opening ssd storage file %s\n", ssd_path);
+    return ;
+  }
+  if((err = ssd_store.read_config(ssd_fd))) {
+    Error("%s failed\n", err);
+    exit(1);
+  }
+#endif
 }
 
 #ifdef NON_MODULAR

Modified: trafficserver/traffic/branches/ssd/iocore/cache/CacheDir.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/CacheDir.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/CacheDir.cc (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/CacheDir.cc Tue Jun 28 09:17:58 2011
@@ -514,7 +514,7 @@ dir_probe(CacheKey *key, Vol *d, Dir *re
 #endif
 Lagain:
   e = dir_bucket(b, seg);
-  if (dir_offset(e))
+  if (dir_offset(e)) {
     do {
       if (dir_compare_tag(e, key)) {
         ink_debug_assert(dir_offset(e));
@@ -545,12 +545,14 @@ Lagain:
           e = dir_delete_entry(e, p, s, d);
           continue;
         }
-      } else
+      } else {
         DDebug("dir_probe_tag", "tag mismatch %X %X vs expected %X", e, dir_tag(e), key->word(3));
+      }
     Lcont:
       p = e;
       e = next_dir(e, seg);
     } while (e);
+  }
   if (collision) {              // last collision no longer in the list, retry
     DDebug("cache_stats", "Incrementing dir collisions");
     CACHE_INC_DIR_COLLISIONS(d->mutex);

Modified: trafficserver/traffic/branches/ssd/iocore/cache/CacheHosting.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/CacheHosting.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/CacheHosting.cc (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/CacheHosting.cc Tue Jun 28 09:17:58 2011
@@ -192,13 +192,18 @@ CacheHostMatcher::NewEntry(matcher_line 
  *   End class HostMatcher
  *************************************************************/
 
-CacheHostTable::CacheHostTable(Cache * c, int typ)
+CacheHostTable::CacheHostTable(Cache * c, int typ
+#ifdef CACHE_SSD
+    , int ssd_typ
+#endif
+    )
 {
-
-
   config_tags = &CacheHosting_tags;
   ink_assert(config_tags != NULL);
 
+#ifdef CACHE_SSD
+  ssd_type = ssd_typ;
+#endif
   type = typ;
   cache = c;
   matcher_name = "[CacheHosting]";;
@@ -423,11 +428,17 @@ CacheHostTable::BuildTableFromString(cha
 int
 CacheHostTable::BuildTable()
 {
-
   // File I/O Locals
   char *file_buf;
   int ret;
 
+#ifdef CACHE_SSD
+  if (ssd_type) {
+    gen_host_rec.Init(type, ssd_type);
+    return 0;
+  }
+#endif
+
   file_buf = readIntoBuffer(config_file_path, matcher_name, NULL);
 
   if (file_buf == NULL) {
@@ -442,7 +453,11 @@ CacheHostTable::BuildTable()
 }
 
 int
-CacheHostRecord::Init(int typ)
+CacheHostRecord::Init(int typ
+#ifdef CACHE_SSD
+    , int ssd_type
+#endif
+    )
 {
 
   int i, j;
@@ -462,7 +477,21 @@ CacheHostRecord::Init(int typ)
       Debug("cache_hosting", "Host Record: %xd, Volume: %d, size: %u", this, cachep->vol_number, cachep->size);
       cp[num_cachevols] = cachep;
       num_cachevols++;
+#ifdef CACHE_SSD
+      if (ssd_type) {
+        for (i = 0; i < cachep->num_vols; ++i) {
+          if (cachep->vols[i]->disk->is_ssd)
+            ++num_vols;
+        }
+      } else {
+        for (i = 0; i < cachep->num_vols; ++i) {
+          if (!cachep->vols[i]->disk->is_ssd)
+            ++num_vols;
+        }
+      }
+#else
       num_vols += cachep->num_vols;
+#endif
     }
   }
   if (!num_cachevols) {
@@ -475,7 +504,14 @@ CacheHostRecord::Init(int typ)
   for (i = 0; i < num_cachevols; i++) {
     CacheVol *cachep1 = cp[i];
     for (j = 0; j < cachep1->num_vols; j++) {
+#ifdef CACHE_SSD
+      if (ssd_type && cachep1->vols[j]->disk->is_ssd)
+        vols[counter++] = cachep1->vols[j];
+      else if (!ssd_type && !cachep1->vols[j]->disk->is_ssd)
+        vols[counter++] = cachep1->vols[j];
+#else
       vols[counter++] = cachep1->vols[j];
+#endif
     }
   }
   ink_assert(counter == num_vols);

Modified: trafficserver/traffic/branches/ssd/iocore/cache/CacheRead.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/CacheRead.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/CacheRead.cc (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/CacheRead.cc Tue Jun 28 09:17:58 2011
@@ -105,6 +105,85 @@ Cache::open_read(Continuation * cont, Ca
   OpenDirEntry *od = NULL;
   CacheVC *c = NULL;
 
+#ifdef CACHE_SSD
+  Dir ssd_result, *last_ssd_collision = NULL;
+  Vol *ssd_vol = key_to_vol(key, hostname, host_len, true);
+  if (ssd_vol != NULL) {
+    {
+      CACHE_TRY_LOCK(ssd_lock, ssd_vol->mutex, mutex->thread_holding);
+      if (!ssd_lock || dir_probe(key, ssd_vol, &ssd_result, &last_ssd_collision)) {
+        c = new_CacheVC(cont);
+        c->first_key = c->key = c->earliest_key = *key;
+        c->vol = ssd_vol;
+        c->vol_backup = vol;
+        vol = ssd_vol;
+        c->vio.op = VIO::READ;
+        c->base_stat = cache_read_active_stat;
+        CACHE_INCREMENT_DYN_STAT(c->base_stat + CACHE_STAT_ACTIVE);
+        CACHE_INCREMENT_DYN_STAT(cache_ssd_read_active_stat);
+        c->request.copy_shallow(request);
+        c->frag_type = CACHE_FRAG_TYPE_HTTP;
+        c->params = params;
+        c->od = NULL;
+        c->f.read_from_ssd = true;
+      }
+      if (!ssd_lock) {
+        Debug("ssd_cache_trylock", "trylock ssd fail in open_read ssd");
+        SET_CONTINUATION_HANDLER(c, &CacheVC::openReadStartHead);
+        CONT_SCHED_LOCK_RETRY(c);
+        return &c->_action;
+      }
+      if (c) {
+        Debug("ssd_cache_probe", "probe hit in ssd");
+        c->f.doc_from_ssd = true;
+        c->dir = c->first_dir = ssd_result;
+        c->last_collision = last_ssd_collision;
+        SET_CONTINUATION_HANDLER(c, &CacheVC::openReadStartHead);
+        switch(c->do_read_call(&c->key)) {
+          case EVENT_DONE: return ACTION_RESULT_DONE;
+          case EVENT_RETURN: goto Lcallreturn;
+          default: return &c->_action;
+        }
+      }
+    }
+    if (!c) {
+      CACHE_INCREMENT_DYN_STAT(cache_ssd_read_failure_stat);
+      CACHE_TRY_LOCK(lock, vol->mutex, mutex->thread_holding);
+      if (!lock || (od = vol->open_read(key)) || dir_probe(key, vol, &result, &last_collision)) {
+        c = new_CacheVC(cont);
+        c->first_key = c->key = c->earliest_key = *key;
+        c->vol = vol;
+        c->vol_backup = ssd_vol;
+        c->vio.op = VIO::READ;
+        c->base_stat = cache_read_active_stat;
+        CACHE_INCREMENT_DYN_STAT(c->base_stat + CACHE_STAT_ACTIVE);
+        c->request.copy_shallow(request);
+        c->frag_type = CACHE_FRAG_TYPE_HTTP;
+        c->params = params;
+        c->od = od;
+      }
+      if (!lock) {
+        Debug("ssd_cache_trylock", "trylock sata fail in open_read sata");
+        SET_CONTINUATION_HANDLER(c, &CacheVC::openReadStartHead);
+        CONT_SCHED_LOCK_RETRY(c);
+        return &c->_action;
+      }
+      if (!c)
+        goto Lmiss;
+      if (c->od)
+        goto Lwriter;
+      Debug("ssd_cache_probe", "probe hit in sata");
+      c->dir = c->first_dir = result;
+      c->last_collision = last_collision;
+      SET_CONTINUATION_HANDLER(c, &CacheVC::openReadStartHead);
+      switch(c->do_read_call(&c->key)) {
+        case EVENT_DONE: return ACTION_RESULT_DONE;
+        case EVENT_RETURN: goto Lcallreturn;
+        default: return &c->_action;
+      }
+    }
+  } else
+#endif
   {
     CACHE_TRY_LOCK(lock, vol->mutex, mutex->thread_holding);
     if (!lock || (od = vol->open_read(key)) || dir_probe(key, vol, &result, &last_collision)) {
@@ -513,13 +592,17 @@ CacheVC::openReadClose(int event, Event 
 {
   NOWARN_UNUSED(e);
   NOWARN_UNUSED(event);
-
   cancel_trigger();
   if (is_io_in_progress()) {
     if (event != AIO_EVENT_DONE)
       return EVENT_CONT;
     set_io_not_in_progress();
   }
+#ifdef CACHE_SSD
+  if (f.l_tag1)
+    goto LWriteSSD;
+  {
+#endif
   CACHE_TRY_LOCK(lock, vol->mutex, mutex->thread_holding);
   if (!lock)
     VC_SCHED_LOCK_RETRY();
@@ -534,6 +617,37 @@ CacheVC::openReadClose(int event, Event 
   }
 #endif
   vol->close_read(this);
+#ifdef CACHE_SSD
+  }
+  f.l_tag1 = true;
+LWriteSSD:
+  if (f.read_done && !f.doc_from_ssd && write2ssd_doc != NULL && f.write_to_ramcache)
+  {
+    MUTEX_TRY_LOCK(ssd_lock, vol_backup->mutex, mutex->thread_holding);
+    if (!ssd_lock) {
+      Debug("ssd_cache_trylock", "trylock ssd fail when read done sata and ready to aggwrite ssd");
+      VC_SCHED_LOCK_RETRY();
+    }
+    f.l_tag1 = false;
+    f.read_done = false;
+    f.write_to_ramcache = false;
+    CacheVC *ssd_vc = new_CacheVC(vol_backup);
+    ssd_vc->f.write_to_ssd = true;
+    ssd_vc->write2ssd_doc = (char *)xmalloc(write2ssd_len);
+    ssd_vc->write2ssd_len = write2ssd_len;
+    memcpy(ssd_vc->write2ssd_doc, write2ssd_doc, write2ssd_len);
+    ssd_vc->vol = vol_backup;
+    ssd_vc->key = first_key;
+    ssd_vc->agg_len = vol_backup->round_to_approx_size((uint32_t) write2ssd_len);
+    vol_backup->agg_todo_size += ssd_vc->agg_len;
+    dir_clear(&ssd_vc->dir);
+    SET_CONTINUATION_HANDLER(ssd_vc, &CacheVC::write2SSDDone);
+    vol_backup->agg.enqueue(ssd_vc);
+    if (!vol_backup->is_io_in_progress()) {
+      vol_backup->aggWrite(EVENT_CALL, NULL);
+    }
+  }
+#endif
   return free_CacheVC(this);
 }
 
@@ -820,6 +934,9 @@ Lread:
     // read has detected that alternate does not exist in the cache.
     // rewrite the vector.
 #ifdef HTTP_CACHE
+#ifdef CACHE_SSD
+    if (!f.read_from_ssd) {
+#endif
     if (!f.read_from_writer_called && frag_type == CACHE_FRAG_TYPE_HTTP) {
       // don't want any writers while we are evacuating the vector
       if (!vol->open_write(this, false, 1)) {
@@ -871,6 +988,9 @@ Lread:
         }
       }
     }
+#ifdef CACHE_SSD
+    }
+#endif
 #endif
     // open write failure - another writer, so don't modify the vector
   Ldone:
@@ -1008,6 +1128,13 @@ CacheVC::openReadStartHead(int event, Ev
         goto Ldone;
       if (vector.get_handles(doc->hdr(), doc->hlen) != doc->hlen) {
         if (buf) {
+#ifdef CACHE_SSD
+	  if (f.doc_from_ssd) {
+	    Note("OpenReadHead failed for cachekey %X : vector inconsistency with %d in ssd cache", key.word(0), doc->hlen);
+	    CACHE_DECREMENT_DYN_STAT(cache_ssd_read_active_stat);
+	    CACHE_INCREMENT_DYN_STAT(cache_ssd_read_failure_stat);
+	  } else
+#endif
           Note("OpenReadHead failed for cachekey %X : vector inconsistency with %d", key.word(0), doc->hlen);
           dir_delete(&key, vol, &dir);
         }
@@ -1029,6 +1156,13 @@ CacheVC::openReadStartHead(int event, Ev
       alternate_tmp = vector.get(alternate_index);
       if (!alternate_tmp->valid()) {
         if (buf) {
+#ifdef CACHE_SSD
+	  if (f.doc_from_ssd) {
+	    Note("OpenReadHead failed for cachekey %X : alternate inconsistency with %d in ssd cache", key.word(0), doc->hlen);
+	    CACHE_DECREMENT_DYN_STAT(cache_ssd_read_active_stat);
+	    CACHE_INCREMENT_DYN_STAT(cache_ssd_read_failure_stat);
+	  } else
+#endif
           Note("OpenReadHead failed for cachekey %X : alternate inconsistency", key.word(0));
           dir_delete(&key, vol, &dir);
         }
@@ -1059,6 +1193,10 @@ CacheVC::openReadStartHead(int event, Ev
     // fragment is there before returning CACHE_EVENT_OPEN_READ
     if (!f.single_fragment)
       goto Learliest;
+#ifdef CACHE_SSD
+    else
+      f.read_done = true;
+#endif
 
 #ifdef HIT_EVACUATE
     if (vol->within_hit_evacuate_window(&dir) &&
@@ -1080,6 +1218,9 @@ CacheVC::openReadStartHead(int event, Ev
     // don't want to go through this BS of reading from a writer if
     // its a lookup. In this case lookup will fail while the document is
     // being written to the cache.
+#ifdef CACHE_SSD
+    if (!f.read_from_ssd) {
+#endif
     OpenDirEntry *cod = vol->open_read(&key);
     if (cod && !f.read_from_writer_called) {
       if (f.lookup) {
@@ -1091,13 +1232,48 @@ CacheVC::openReadStartHead(int event, Ev
       SET_HANDLER(&CacheVC::openReadFromWriter);
       return handleEvent(EVENT_IMMEDIATE, 0);
     }
+#ifdef CACHE_SSD
+    }
+#endif
     if (dir_probe(&key, vol, &dir, &last_collision)) {
+#ifdef CACHE_SSD
+      if (f.read_from_ssd && !f.doc_from_ssd) {
+        f.doc_from_ssd = true;
+      }
+#endif
       first_dir = dir;
       int ret = do_read_call(&key);
       if (ret == EVENT_RETURN)
         goto Lcallreturn;
       return ret;
     }
+#ifdef CACHE_SSD
+    else {
+      if (f.read_from_ssd && !f.doc_from_ssd) {
+        CACHE_DECREMENT_DYN_STAT(cache_ssd_read_active_stat);
+        CACHE_INCREMENT_DYN_STAT(cache_ssd_read_failure_stat);
+        f.read_from_ssd = false;
+        last_collision = NULL;
+        od = NULL;
+        Vol *tmp = vol_backup;
+        vol_backup = vol;
+        vol = tmp;
+        dir_clear(&dir);
+        dir_clear(&first_dir);
+        dir_clear(&earliest_dir);
+        buf.clear();
+        first_buf.clear();
+        blocks.clear();
+        writer_buf.clear();
+        alternate.destroy();
+        vector.clear();
+        io.aio_result = 0;
+        io.aiocb.aio_nbytes = 0;
+        io.aiocb.aio_reqprio = AIO_DEFAULT_PRIORITY;
+        VC_SCHED_LOCK_RETRY();
+      }
+    }
+#endif
   }
 Ldone:
   if (!f.lookup) {

Modified: trafficserver/traffic/branches/ssd/iocore/cache/CacheWrite.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/CacheWrite.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/CacheWrite.cc (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/CacheWrite.cc Tue Jun 28 09:17:58 2011
@@ -547,6 +547,26 @@ CacheVC::evacuateDocDone(int event, Even
   return free_CacheVC(this);
 }
 
+#ifdef CACHE_SSD
+int
+CacheVC::write2SSDDone(int event, Event *e)
+{
+  NOWARN_UNUSED(e);
+  NOWARN_UNUSED(event);
+
+  cancel_trigger();
+  {
+    MUTEX_TRY_LOCK(ssd_lock, vol->mutex, mutex->thread_holding);
+    if (!ssd_lock) {
+      Debug("ssd_cache_trylock", "trylock ssd fail when write2SSDDone");
+      VC_SCHED_LOCK_RETRY();
+    }
+    dir_insert(&key, vol, &dir);
+  }
+  return free_CacheVC(this);
+}
+#endif
+
 static int
 evacuate_fragments(CacheKey *key, CacheKey *earliest_key, int force, Vol *vol)
 {
@@ -741,6 +761,9 @@ agg_copy(char *p, CacheVC *vc)
   Vol *vol = vc->vol;
   off_t o = vol->header->write_pos + vol->agg_buf_pos;
 
+#ifdef CACHE_SSD
+  if (!vc->f.write_to_ssd) {
+#endif
   if (!vc->f.evacuator) {
     Doc *doc = (Doc *) p;
     IOBufferBlock *res_alt_blk = 0;
@@ -882,6 +905,20 @@ agg_copy(char *p, CacheVC *vc)
 
     return l;
   }
+#ifdef CACHE_SSD
+  } else {
+    Doc *doc = (Doc *) vc->write2ssd_doc;
+    doc->sync_serial = vc->vol->header->sync_serial;
+    doc->write_serial = vc->vol->header->write_serial;
+    memcpy(p, doc, doc->len);
+
+    dir_set_approx_size(&vc->dir, vc->agg_len);
+    dir_set_offset(&vc->dir, offset_to_vol_offset(vc->vol, o));
+    dir_set_phase(&vc->dir, vc->vol->header->phase);
+
+    return vc->agg_len;
+  }
+#endif
 }
 
 inline void
@@ -994,8 +1031,9 @@ Lagain:
       while (last && UINT_WRAP_LT(c->write_serial, last->write_serial))
         last = (CacheVC*)last->link.prev;
       sync.insert(c, last);
-    } else if (c->f.evacuator)
+    } else if (c->f.evacuator) {
       c->handleEvent(AIO_EVENT_DONE, 0);
+    }
     else
       tocall.enqueue(c);
     c = n;
@@ -1069,7 +1107,11 @@ Lagain:
 Lwait:
   int ret = EVENT_CONT;
   while ((c = tocall.dequeue())) {
-    if (event == EVENT_CALL && c->mutex->thread_holding == mutex->thread_holding)
+    if (event == EVENT_CALL && c->mutex->thread_holding == mutex->thread_holding
+#ifdef CACHE_SSD
+        && !c->f.write_to_ssd
+#endif
+        )
       ret = EVENT_RETURN;
     else
       c->initial_thread->schedule_imm_signal(c, AIO_EVENT_DONE);
@@ -1763,6 +1805,34 @@ Cache::open_write(Continuation *cont, Ca
   CACHE_INCREMENT_DYN_STAT(c->base_stat + CACHE_STAT_ACTIVE);
   c->pin_in_cache = (uint32_t) apin_in_cache;
 
+#ifdef CACHE_SSD
+  Vol *ssd_vol = key_to_vol(key, hostname, host_len, true);
+  if (ssd_vol != NULL)
+  {
+    Continuation *remove_ssd = new_CacheRemoveCont();
+    CACHE_TRY_LOCK(lock, remove_ssd->mutex, this_ethread());
+    ink_assert(lock);
+    Vol *vol = ssd_vol;
+    // coverity[var_decl]
+    Dir result;
+    dir_clear(&result);           // initialized here, set result empty so we can recognize missed lock
+    ProxyMutexPtr mutex = remove_ssd->mutex;
+
+    CacheVC *c = new_CacheVC(remove_ssd);
+    c->vio.op = VIO::NONE;
+    c->frag_type = type;
+    c->base_stat = cache_remove_active_stat;
+    CACHE_INCREMENT_DYN_STAT(c->base_stat + CACHE_STAT_ACTIVE);
+    c->first_key = c->key = *key;
+    c->vol = vol;
+    c->dir = result;
+    c->f.remove = 1;
+
+    SET_CONTINUATION_HANDLER(c, &CacheVC::removeSSD);
+    int ret = c->removeSSD(EVENT_IMMEDIATE, 0);
+    Debug("ssd_cache_remove", "remove stale object in ssd when write sata: %d", ret);
+  }
+#endif
   {
     CACHE_TRY_LOCK(lock, c->vol->mutex, cont->mutex->thread_holding);
     if (lock) {
@@ -1784,6 +1854,9 @@ Cache::open_write(Continuation *cont, Ca
         // document doesn't exist, begin write
         goto Lmiss;
       } else {
+#ifdef CACHE_SSD
+        c->f.read_before_write = true;
+#endif
         c->od->reading_vec = 1;
         // document exists, read vector
         SET_CONTINUATION_HANDLER(c, &CacheVC::openWriteStartDone);

Modified: trafficserver/traffic/branches/ssd/iocore/cache/I_Cache.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/I_Cache.h?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/I_Cache.h (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/I_Cache.h Tue Jun 28 09:17:58 2011
@@ -170,6 +170,11 @@ struct CacheVConnection:public VConnecti
   virtual void get_http_info(CacheHTTPInfo **info) = 0;
 #endif
 
+#ifdef CACHE_SSD
+  virtual bool stat_ssd() {
+    return false;
+  }
+#endif
   virtual bool is_ram_cache_hit() = 0;
   virtual bool set_disk_io_priority(int priority) = 0;
   virtual int get_disk_io_priority() = 0;

Modified: trafficserver/traffic/branches/ssd/iocore/cache/P_CacheDisk.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/P_CacheDisk.h?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/P_CacheDisk.h (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/P_CacheDisk.h Tue Jun 28 09:17:58 2011
@@ -103,12 +103,18 @@ struct CacheDisk: public Continuation
   DiskVol *free_blocks;
   int num_errors;
   int cleared;
+#ifdef CACHE_SSD
+  bool is_ssd;
+#endif
 
   CacheDisk()
     : Continuation(new_ProxyMutex()), header(NULL),
       path(NULL), header_len(0), len(0), start(0), skip(0),
       num_usable_blocks(0), fd(-1), free_space(0), wasted_space(0),
       disk_vols(NULL), free_blocks(NULL), num_errors(0), cleared(0)
+#ifdef CACHE_SSD
+  , is_ssd(false)
+#endif
   { }
 
    ~CacheDisk();

Modified: trafficserver/traffic/branches/ssd/iocore/cache/P_CacheHosting.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/P_CacheHosting.h?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/P_CacheHosting.h (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/P_CacheHosting.h Tue Jun 28 09:17:58 2011
@@ -35,7 +35,11 @@ struct Cache;
 
 struct CacheHostRecord
 {
-  int Init(int typ);
+  int Init(int typ
+#ifdef CACHE_SSD
+      , int ssd_type = false
+#endif
+      );
   int Init(matcher_line *line_info, int typ);
   void UpdateMatch(CacheHostResult *r, char *rd);
   void Print();
@@ -108,7 +112,11 @@ class CacheHostTable
 public:
   // Parameter name must not be deallocated before this
   //  object is
-  CacheHostTable(Cache *c, int typ);
+  CacheHostTable(Cache *c, int typ
+#ifdef CACHE_SSD
+      , int ssd_type = false
+#endif
+      );
    ~CacheHostTable();
   int BuildTable();
   int BuildTableFromString(char *str);
@@ -125,6 +133,9 @@ public:
     IOCORE_RegisterConfigUpdateFunc("proxy.config.cache.hosting_filename", CacheHostTable::config_callback, (void *) p);
   }
 
+#ifdef CACHE_SSD
+  int ssd_type;
+#endif
   int type;
   Cache *cache;
   int m_numEntries;
@@ -152,7 +163,11 @@ struct CacheHostTableConfig: public Cont
   {
     (void) e;
     (void) event;
-    CacheHostTable *t = NEW(new CacheHostTable((*ppt)->cache, (*ppt)->type));
+    CacheHostTable *t = NEW(new CacheHostTable((*ppt)->cache, (*ppt)->type
+#ifdef CACHE_SSD
+    , (*ppt)->ssd_type)
+#endif
+    );
     CacheHostTable *old = (CacheHostTable *) ink_atomic_swap_ptr(&t, ppt);
     new_Deleter(old, CACHE_MEM_FREE_TIMEOUT);
     return EVENT_DONE;

Modified: trafficserver/traffic/branches/ssd/iocore/cache/P_CacheInternal.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/iocore/cache/P_CacheInternal.h?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/iocore/cache/P_CacheInternal.h (original)
+++ trafficserver/traffic/branches/ssd/iocore/cache/P_CacheInternal.h Tue Jun 28 09:17:58 2011
@@ -130,6 +130,11 @@ enum
   cache_read_active_stat,
   cache_read_success_stat,
   cache_read_failure_stat,
+#ifdef CACHE_SSD
+  cache_ssd_read_active_stat,
+  cache_ssd_read_success_stat,
+  cache_ssd_read_failure_stat,
+#endif
   cache_write_active_stat,
   cache_write_success_stat,
   cache_write_failure_stat,
@@ -349,6 +354,14 @@ struct CacheVC: public CacheVConnection
   int evacuateDocDone(int event, Event *e);
   int evacuateReadHead(int event, Event *e);
 
+#ifdef CACHE_SSD
+  int write2SSDDone(int event, Event *e);
+  int removeSSD(int event, Event *e);
+  virtual bool stat_ssd() {
+    return true;
+  }
+#endif
+
   void cancel_trigger();
   virtual int64_t get_object_size();
 #ifdef HTTP_CACHE
@@ -426,7 +439,13 @@ struct CacheVC: public CacheVConnection
   Frag *frag;           // arraylist of fragment offset
   Frag integral_frags[INTEGRAL_FRAGS];
   Vol *vol;
+#ifdef CACHE_SSD
+  Vol *vol_backup;
+  char *write2ssd_doc;
+  int write2ssd_len;
+#endif
   Dir *last_collision;
+
   Event *trigger;
   CacheKey *read_key;
   ContinuationHandler save_handler;
@@ -479,6 +498,15 @@ struct CacheVC: public CacheVConnection
 #ifdef HIT_EVACUATE
       unsigned int hit_evacuate:1;
 #endif
+#ifdef CACHE_SSD
+      unsigned int doc_from_ssd:1;
+      unsigned int read_from_ssd:1;
+      unsigned int write_to_ssd:1;
+      unsigned int write_to_ramcache:1;
+      unsigned int read_before_write:1;
+      unsigned int read_done:1;
+      unsigned int l_tag1:1;//local variable in CacheVC::openReadClose
+#endif
     } f;
   };
   // BTF optimization used to skip reading stuff in cache partition that doesn't contain any
@@ -556,6 +584,12 @@ free_CacheVC(CacheVC *cont)
     CACHE_DECREMENT_DYN_STAT(cont->base_stat + CACHE_STAT_ACTIVE);
     if (cont->closed > 0) {
       CACHE_INCREMENT_DYN_STAT(cont->base_stat + CACHE_STAT_SUCCESS);
+#ifdef CACHE_SSD
+      if (cont->f.doc_from_ssd) {
+        CACHE_DECREMENT_DYN_STAT(cache_ssd_read_active_stat);
+        CACHE_INCREMENT_DYN_STAT(cache_ssd_read_success_stat);
+      }
+#endif
     }                             // else abort,cancel
   }
   ink_debug_assert(mutex->thread_holding == this_ethread());
@@ -572,6 +606,12 @@ free_CacheVC(CacheVC *cont)
   cont->io.aio_result = 0;
   cont->io.aiocb.aio_nbytes = 0;
   cont->io.aiocb.aio_reqprio = AIO_DEFAULT_PRIORITY;
+#ifdef CACHE_SSD
+  if (cont->write2ssd_doc != NULL) {
+    xfree(cont->write2ssd_doc);
+    cont->write2ssd_doc = NULL;
+  }
+#endif
 #ifdef HTTP_CACHE
   cont->request.reset();
   cont->vector.clear();
@@ -952,6 +992,9 @@ struct Cache
   volatile int ready;
   int64_t cache_size;             //in store block size
   CacheHostTable *hosttable;
+#ifdef CACHE_SSD
+  CacheHostTable *ssd_hosttable;
+#endif
   volatile int total_initialized_vol;
   int scheme;
 
@@ -993,11 +1036,19 @@ struct Cache
 
   int open_done();
 
-  Vol *key_to_vol(CacheKey *key, char *hostname, int host_len);
+  Vol *key_to_vol(CacheKey *key, char *hostname, int host_len
+#ifdef CACHE_SSD
+      , int ssd_type = false
+#endif
+      );
 
   Cache()
     : cache_read_done(0), total_good_nvol(0), total_nvol(0), ready(CACHE_INITIALIZING), cache_size(0),  // in store block size
-      hosttable(NULL), total_initialized_vol(0), scheme(CACHE_NONE_TYPE)
+      hosttable(NULL),
+#ifdef CACHE_SSD
+      ssd_hosttable(NULL),
+#endif
+      total_initialized_vol(0), scheme(CACHE_NONE_TYPE)
     { }
 };
 

Modified: trafficserver/traffic/branches/ssd/lib/ts/ink_config.h.in
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/lib/ts/ink_config.h.in?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/lib/ts/ink_config.h.in (original)
+++ trafficserver/traffic/branches/ssd/lib/ts/ink_config.h.in Tue Jun 28 09:17:58 2011
@@ -159,6 +159,8 @@
 # define HTTP_CACHE                     1
 #endif
 
+# define CACHE_SSD                      1
+
 #if TS_HAS_PURIFY
 # define PURIFY                         1
 #endif

Modified: trafficserver/traffic/branches/ssd/mgmt/AddConfigFilesHere.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/mgmt/AddConfigFilesHere.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/mgmt/AddConfigFilesHere.cc (original)
+++ trafficserver/traffic/branches/ssd/mgmt/AddConfigFilesHere.cc Tue Jun 28 09:17:58 2011
@@ -69,6 +69,7 @@ initializeRegistry()
   configFiles->addFile("log_hosts.config", false);
   configFiles->addFile("logs_xml.config", false);
   configFiles->addFile("storage.config", false);
+  configFiles->addFile("storage_ssd.config", false);
   configFiles->addFile("socks.config", false);
   configFiles->addFile("proxy.pac", false);
   configFiles->addFile("wpad.dat", false);

Modified: trafficserver/traffic/branches/ssd/mgmt/RecordsConfig.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/mgmt/RecordsConfig.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/mgmt/RecordsConfig.cc (original)
+++ trafficserver/traffic/branches/ssd/mgmt/RecordsConfig.cc Tue Jun 28 09:17:58 2011
@@ -933,6 +933,13 @@ RecordElement RecordsConfig[] = {
   ,
   {RECT_CONFIG, "proxy.config.cache.vary_on_user_agent", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
+  //##############################################################################
+  //#
+  //# SSD Cache
+  //#
+  //##############################################################################
+  {RECT_CONFIG, "proxy.config.cache.ssd_filename", RECD_STRING, "storage_ssd.config", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL}
+  ,
   //  # 0 - MD5 hash
   //  # 1 - MMH hash
   {RECT_CONFIG, "proxy.config.cache.url_hash_method", RECD_INT, "1", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL}

Modified: trafficserver/traffic/branches/ssd/mgmt/cli/ShowCmd.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/mgmt/cli/ShowCmd.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/mgmt/cli/ShowCmd.cc (original)
+++ trafficserver/traffic/branches/ssd/mgmt/cli/ShowCmd.cc Tue Jun 28 09:17:58 2011
@@ -2217,6 +2217,10 @@ ShowHttpStats()
   TSInt origin_server_response_header_total_size = -1;
   TSInt current_server_connections = -1;
   TSInt current_server_transactions = -1;
+#ifdef CACHE_SSD
+  TSInt ssd_serve_total_size = -1;
+  Cli_RecordGetInt("proxy.process.http.ssd_serve_total_size", &ssd_serve_total_size);
+#endif
   //get value
   Cli_RecordGetInt("proxy.process.http.user_agent_response_document_total_size",
                    &user_agent_response_document_total_size);
@@ -2235,6 +2239,9 @@ ShowHttpStats()
   Cli_Printf("--Client--\n");
   Cli_Printf("Total Document Bytes ----- %d MB\n", user_agent_response_document_total_size / (1024 * 1024));
   Cli_Printf("Total Header Bytes ------- %d MB\n", user_agent_response_header_total_size / (1024 * 1024));
+#ifdef CACHE_SSD
+  Cli_Printf("Total SSD Serve Bytes ---- %d MB\n", ssd_serve_total_size/ (1024 *1024));
+#endif
   Cli_Printf("Total Connections -------- %d\n", current_client_connections);
   Cli_Printf("Transactins In Progress -- %d\n", current_client_transactions);
   Cli_Printf("--Server--\n");

Modified: trafficserver/traffic/branches/ssd/proxy/config/Makefile.am
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/config/Makefile.am?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/config/Makefile.am (original)
+++ trafficserver/traffic/branches/ssd/proxy/config/Makefile.am Tue Jun 28 09:17:58 2011
@@ -19,11 +19,13 @@
 SUBDIRS = body_factory
 EXTRA_DIST = \
   records.config.default.in \
+  storage_ssd.config.default.in \
   storage.config.default.in
 
 sysconfdir = $(pkgsysconfdir)
 nodist_sysconf_DATA = \
   records.config.default \
+  storage_ssd.config.default \
   storage.config.default
 
 dist_sysconf_DATA =	\

Added: trafficserver/traffic/branches/ssd/proxy/config/storage_ssd.config.default.in
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/config/storage_ssd.config.default.in?rev=1140493&view=auto
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/config/storage_ssd.config.default.in (added)
+++ trafficserver/traffic/branches/ssd/proxy/config/storage_ssd.config.default.in Tue Jun 28 09:17:58 2011
@@ -0,0 +1 @@
+@rel_cachedir@ 256M

Modified: trafficserver/traffic/branches/ssd/proxy/http/HttpCacheSM.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/http/HttpCacheSM.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/http/HttpCacheSM.cc (original)
+++ trafficserver/traffic/branches/ssd/proxy/http/HttpCacheSM.cc Tue Jun 28 09:17:58 2011
@@ -114,6 +114,11 @@ HttpCacheSM::state_cache_open_read(int e
     ink_assert(cache_read_vc == NULL);
     open_read_cb = true;
     cache_read_vc = (CacheVConnection *) data;
+#ifdef CACHE_SSD
+    if (cache_read_vc->stat_ssd()) {
+      master_sm->t_state.doc_from_ssd = ((CacheVC *)cache_read_vc)->f.doc_from_ssd;
+    }
+#endif
     master_sm->handleEvent(event, data);
     break;
 

Modified: trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.cc (original)
+++ trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.cc Tue Jun 28 09:17:58 2011
@@ -448,6 +448,11 @@ register_stat_callbacks()
                      "proxy.process.http.server_raw_transaction_time",
                      RECD_INT, RECP_NULL, (int) http_server_raw_transaction_time_stat, RecRawStatSyncSum);
 
+#ifdef CACHE_SSD
+  RecRegisterRawStat(http_rsb, RECT_PROCESS,
+                     "proxy.process.http.ssd_serve_total_size",
+                     RECD_INT, RECP_NULL, (int) http_ssd_serve_total_size_stat, RecRawStatSyncSum);
+#endif
   RecRegisterRawStat(http_rsb, RECT_PROCESS,
                      "proxy.process.http.user_agent_request_header_total_size",
                      RECD_INT, RECP_NULL, (int) http_user_agent_request_header_total_size_stat, RecRawStatSyncSum);

Modified: trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.h?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.h (original)
+++ trafficserver/traffic/branches/ssd/proxy/http/HttpConfig.h Tue Jun 28 09:17:58 2011
@@ -164,6 +164,9 @@ enum
   http_request_taxonomy_i1_n1_m1_stat,
   http_icp_suggested_lookups_stat,
 
+#ifdef CACHE_SSD
+  http_ssd_serve_total_size_stat,
+#endif
   // document size stats
   http_user_agent_request_header_total_size_stat,
   http_user_agent_response_header_total_size_stat,

Modified: trafficserver/traffic/branches/ssd/proxy/http/HttpSM.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/http/HttpSM.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/http/HttpSM.cc (original)
+++ trafficserver/traffic/branches/ssd/proxy/http/HttpSM.cc Tue Jun 28 09:17:58 2011
@@ -4053,6 +4053,9 @@ HttpSM::do_http_server_open(bool raw)
 {
   Debug("http_track", "entered inside do_http_server_open");
 
+#ifdef CACHE_SSD
+  t_state.doc_from_ssd = false;
+#endif
   ink_assert(server_entry == NULL);
 
   // ua_entry can be null if a scheduled update is also a reverse proxy

Modified: trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.cc?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.cc (original)
+++ trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.cc Tue Jun 28 09:17:58 2011
@@ -8816,6 +8816,12 @@ HttpTransact::update_size_and_time_stats
   // times
   HTTP_SUM_TRANS_STAT(http_total_transactions_time_stat, total_time);
 
+#ifdef CACHE_SSD
+  if (s->doc_from_ssd) {
+    HTTP_SUM_TRANS_STAT(http_ssd_serve_total_size_stat, user_agent_response_header_size);
+    HTTP_SUM_TRANS_STAT(http_ssd_serve_total_size_stat, user_agent_response_body_size);
+  }
+#endif
   // sizes
   HTTP_SUM_TRANS_STAT(http_user_agent_request_header_total_size_stat, user_agent_request_header_size);
   HTTP_SUM_TRANS_STAT(http_user_agent_response_header_total_size_stat, user_agent_response_header_size);

Modified: trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.h?rev=1140493&r1=1140492&r2=1140493&view=diff
==============================================================================
--- trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.h (original)
+++ trafficserver/traffic/branches/ssd/proxy/http/HttpTransact.h Tue Jun 28 09:17:58 2011
@@ -1056,6 +1056,9 @@ public:
     OverridableHttpConfigParams *txn_conf;
     OverridableHttpConfigParams my_txn_conf; // Storage for plugins, to avoid malloc
     
+#ifdef CACHE_SSD
+    bool doc_from_ssd;
+#endif
     // Methods
     void
     init()
@@ -1145,6 +1148,9 @@ public:
         pristine_url(),
         api_skip_all_remapping(false),
         txn_conf(NULL)
+#ifdef CACHE_SSD
+    , doc_from_ssd(false)
+#endif
     {
       int i;
       char *via_ptr = via_string;