Upcoming Events

Executive conference

Cloud Connect March 16-18

Comprehensive thought leadership for executives, IT professionals and developers. Topics include: the ROI, cost and economics of on-demand computing; Migration strategies to move from on-premise to cloud-based IT; Vertical cloud specialization, tailoring features and architectures to specific applications, industries, and customer ecosystems

More Events »

Subscribe to Newsletter

  • Keep up with all of the latest news and analysis on the fast-moving IT industry with Network Computing newsletters.
Sign Up


Listing 1. Pseudo-code implementation of restart algorithms.

A. The client functions

void newdownload(char* filename)
{
  // The client UI will call this function if user
  // wants to download a file from the beginning,
  // not restart an aborted file transfer procedure
  //
  long tbt = 0;                   // total bytes transferred
  char buf[2048];                 // buffer
  long bt;                        // bytes transferred in
                                  // a single block
  int fd;                         // local file descriptor
  
  fd = _open(filename, O_WRONLY); // Create a new local file
  bt = svr_read(&buf);        // returns buf size
  while (bt > 0) {
  
     if (isrestartmarker(buf)){   // if buf is a restart marker
 
        updatelogservertimestamp(filename,buf); // then update Log file
     } else {
        tbt = tbt + bt;           // increment total bytes transferred
        updatelogbytesize(filename, tbt);
        _write(fd, buf, sizeof(buf));
     };
     bt = svr_read(&buf);
  };
  _close(fd);                     // close local file
}

void restartdownload(char* filename)
{
  // The client UI will call this function if user
  // wants to restart aborted file transfer process
  //
  long tbt = 0;                   // total bytes transferred
  char buf[2048];                 // buffer
  long bt;                        // bytes transferred in a single block
  int fd;                         // local file descriptor
  TIMESTAMP sts;                  // last recorded server timestamp in Log 
  TIMESTAMP cts;                  // last recorded client timestamp in Log 
  int ret;                        // return code for error recovery
  
  // Check if the local file size matches that in Transfer Log
  //
  tbt = getlogbytes
ize(filename);
  sts = getlogservertimestamp(filename);
  cts = getlogclienttimestamp(filename);
  fd = _open(filename, O_APPEND); // Create a new local file
  if (tbt! = _filelength(fd) ||
     cts! = getclientfiletimetstamp(filename)) {
                                  // local file has changed 
                                  // since download
     _close(fd);                  // abort restart procedure
     return();
  };
  ret = svr_restart(filename,     // ask server to start 
                  tbt,            // (RPC Call) 
                  sts);     
  if (ret == -1) goto shutdown;   // error recovery     
  bt = svr_read(&buf);           
  while (bt > 0) {
                                  // if buf is a restart marker 
                                  // then update Log file
     if (isrestartmarker(buf)) {
         updatelogtimestamp(filename, buf);
     } else {
         tbt = tbt + bt;          // increment total bytes 
                                  // transferred     
         u
pdatelogbytesize(filename, tbt);
         _write(fd, buf, sizeof(buf));
     };
     bt = svr_read(&buf);
  };
  shutdown:
  close(fd);                      // close local file
}

void updatelogservertimestamp(char* filename,char* buf)
{
  int TSLENGTH = 8;               // Timestamp length
  int fd;                         // file descriptor of log file
  LOGSTRUCT ls = NULL;
  char t[8];
  fd = _open(filename, O_RDWR);
  while (read(fd, ls, sizeof(LOGSTRUCT))) {
     if (strcmp(ls.filename, filename) == 0) {
                                  // I found the Log record!
        strncpy(t, ls.filename, TSLENGTH);       
                                  // get the timestamp out of buf
        ls.rt = (TIMESTAMP)t;  
                                  // cast into timestamp
        _write(fd, ls);
        exit;
     };
  };
  _close(fd);
}

void updatelogclienttimestamp(char* filename, char* buf)
{
  int TSLENGTH = 8;               // Timestamp length
  int fd;                         // file descriptor of l
og file
  LOGSTRUCT ls = NULL;
  char t[8];
  fd = _open(filename, O_RDWR);
  while (read(fd, ls, sizeof(LOGSTRUCT))) {
     if (strcmp(ls.filename, filename) == 0) {
                                  // I found the Log record!
        strncpy(t, ls.filename, TSLENGTH);       
                                  // get the timestamp out of buf
        ls.ct = (TIMESTAMP)t;    
                                  // cast into timestamp
        _write(fd, ls);
        exit;
     };
  };
  _close(fd);
}

updatelogbytesize(char* filename, long tbt)
{
  int fd;                         // file descriptor of log file
  LOGSTRUCT ls = NULL;
  fd = _open(filename, O_RDWR);
  while (read(fd, ls, sizeof(LOGSTRUCT))) {
     if (strcmp(ls.filename, filename) == 0) {
                                  // I found the Log record!
        ls.bytestransferred = tbt;  
        _write(fd, ls);
        exit;
     };
  };
  _close(fd);
}

TIMESTAMP getlogservertimestamp(char* filename)
{
  int fd;                         // file descri
ptor of log file
  LOGSTRUCT ls = NULL;
  fd = _open(filename, O_RDWR);
  while (read(fd, ls, sizeof(LOGSTRUCT))) {
     if (strcmp(ls.filename, filename) == 0) { // I found the Log record!
        return ls.rt; 
                                  // return timestamp
     };
  };
  _close(fd);
  return NULL;
}

TIMESTAMP getlogclienttimestamp(char* filename)
{
  int fd;                         // file descriptor of log file
  LOGSTRUCT ls = NULL;
  fd = _open(filename, O_RDWR);
  while (read(fd, ls, sizeof(LOGSTRUCT))) {
     if (strcmp(ls.filename, filename) == 0) {
                                  // I found the Log record!
        return ls.ct; 
                                  // return timestamp
     };
  };
  _close(fd);
  return NULL;
}


long getlogbytesize(char *filename)
{
  int fd;                         // file descriptor of log file
  LOGSTRUCT ls = NULL;
  fd = _open(filename, O_RDONLY);
  while (read(fd, ls, sizeof(LOGSTRUCT))) {
     if (strcmp(ls.filename, filename) == 0) {

                                  // I found the Log record!
        return ls.bytestransferred;
     };
  };
  _close(fd);
  return 0;
}

TIMESTAMP getclientfiletimestamp(char *filename)
{
  TIMESTAMP t = NULL;
  int fd;                         // file descriptor of log file
  char buf[2048];
  fd = _open(filename, O_RDONLY);
  if (fd > 0) {
     t = _fstat(fd, &buffer);
     _close(fd);
  };
  return t.st_time;
}



B. The server functions

static LOGSTRUCT ls;
static int fd;
static int tbt;                   // total bytes transferred 
                                  // during this session
static int rc;                    // counter for restart marker intervals
#define RESTART_INTERVAL 100000
int svr_restart(char* filename, long tbt, TIMESTAMP ts)
{
  int c = 2048;
  char buf[2048];
  struct _stat buffer;

  fd = _open(filename, O_RDONLY);
  _fstat(fd, &buffer);
  if (buffer.st_time! = ts) return -1; 
                                  // file has changed!
  while (tbt 
> 0) {               // Otherwise, move file pointer 
                                  // by tbt bytes
     if (tbt < c) c = tbt;
     read(fd, buf, c);
     tbt = tbt - c;
  };
}

int svr_read(char* filename,char **buf)
{
  int c = 2048, n;
  struct _stat buffer;
        
  strcpy(ls.filename, filename);
  if (rc > RESTART_INTERVAL) {  
                                  // Send Restart Marker
     rc = 0;                      // every 100K bytes
     ls.bytestransferred = tbt;
     _fstat(fd, &buffer);
     ls.ts = buffer.st_time;
     buf = (char **)ls; 
  } else {                        // else just move the
     n = _read(fd, *buf, c);      // data down the pipe
     tbt = tbt + n;
     rc = rc + n;
  };
  if (n == 0) _close(fd);         // close the file when EOF
  return(strlen(*buf));
};

Print This Page


e-mail Send as e-mail

Best of the Web

Data deduplication: Declawing the clones

Data deduplication is emerging as a critically important new arrow in the storage administrator's quiver to answer hard questions about the increasing problem in storage growth costs.

Quick Read

Compression, Encryption, Deduplication, and Replication: Strange Bedfellows

One of the great ironies of storage technology is the inverse relationship between efficiency and security: Adding performance or reducing storage requirements almost always results in reducing the confidentiality, integrity, or availability of a system.

Quick Read

WAN Optimization Whitelists and Blacklists

Optimization is a fantastic way of saving money and creating really happy customers at the same time, but it doesn't work flawlessly for all applications.

Quick Read

WAN Optimization as a Managed Service: It's Not About the Cost

This insight examines how organizations outsourcing their WAN optimization initiatives to a third-party go about achieving their goals for application performance, reducing operational costs, and streamlining enterprise infrastructure.

Quick Read

  Sponsored Links

Premium Content

Data Centers Gone Wild
February 22, 2010

NWC


Salary

Video