🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.jbuilder.java.api
Article #919

Re: OutOfMemoryError

#919
From: Alan Shiers
Date: Thu, 04 Jul 2002 17:31
572 lines
19380 bytes
Hi there,

Sure, I'll provide you with the method receiveFile() which is on the
server-side app and uploadFile() which is on the client-side app.  Also,
I'll include my worker_thread class that you might see how I'm trying to
split the proceedure on the client-side app.

To reiterate, my immediate problem is just getting the while loop in the
receiveFile() method to collect all
incoming data without hanging.  It's just not getting the EOF to trigger
it to leave the loop.

Once that issue is solved, then I have to re-encorporate the
request_workerThread class and thereby splitting the procedure between
uploadFile() and the worker thread.  You might ask, "Why am I doing this
to begin with?".  The reason is simple. You will notice in the
uploadFile() method I send the fileLengh to the server app. 
receiveFile() takes that file size value and calls another method called
isEnoughSpaceAvailable(fileLength);

isEnoughSpaceAvailable(fileLength) determines if there is enough disk
space in the user's home directory to accomodate the file being
uploaded. If there is, then a message is sent back to the client app
giving the OK to "proceed".  Otherwise, it sends a message saying that
the "WebSpaceFull".  

So, you see, request_workerThread class simple allows me to cause the
program to wait a bit for a response from the server app before
proceeding with the upload.

I hope this all helps you to help me get this all straightened out.

Please advise,

Alan Shiers

********************************************************
First, the receiveFile() method (server side):

private void receiveFile(String pathFilename)
  {
    //System.out.println("Incoming path: " + pathFilename);
    //this method is called when a file is being uploaded to the server
    //and is to be saved at the specified directory on the server.

    /*Before we save any file, we need to ensure there is
     *enough free space available in the user's
     *home directory to accomodate it depending on
     *how much initial space was allotted to the user via
     *his Member Profile. If there is no space left,
     *we simply return out of here.
     */

    int fileLength = 0;
    try
    {
      //System.out.println("Trying to read int");
      fileLength = input.readInt();
    }
    catch(IOException ioe){ioe.printStackTrace();}

    boolean enoughSpace = isEnoughSpaceAvailable(fileLength);
    //System.out.println("enoughSpace = " + enoughSpace);
    if (enoughSpace == false) return;

    File myFile = new File(pathFilename);
    byte[] buf;
    FileOutputStream fileOut = null;

    try
    {
       myFile.createNewFile(); //create the file
       if(myFile.exists()) //Method exists() throws a SecurityException
if
                          //there is an access violation.
       {
          try
          {
            fileOut = new FileOutputStream(myFile);
          }
          catch(FileNotFoundException fnfe)
          {
            System.out.println("receiveFile() function -
FileNotFoundException\n");
            fnfe.printStackTrace();
          }
          //We're going to read in the data in chunks of 128 bytes.
          buf = new byte[128];
          //load up the array
          int n;
          while((n = input.read(buf)) >= 0) //<<< Hangs and waits for
EOF, but never gets it.
          {  System.out.print(n + ", ");
            //write it to the file
            fileOut.write(buf);
          }
          /*for(int i = 128; i <= fileLength + 128; i = i + 128)
//<<<Alternate means of getting the data, however, not perfect
          {
            n = input.read(buf);
            if(n == -1)
            {
              System.out.println("breaking");
              break;
            }
            fileOut.write(buf);
          }*/
          //Close the stream
          if(fileOut != null)
            fileOut.close();
          System.out.println("Closed stream");
          output.writeInt(session.UPLOAD_SUCCESSFUL);
          output.flush();
       }
    }
    catch(SecurityException se)
    {
      if(DirAdmin.hasInterface)
        myServer.display("SecurityException occurred in method
ReceiveFile");
      else
        System.out.println("SecurityException occurred in method
ReceiveFile");
      try
      {
        output.writeInt(session.UPLOAD_UNSUCCESSFUL_SECURITY_EXCEPTION);
        //Close the stream
        if(fileOut != null)
          fileOut.close();
        output.flush();
      }
      catch(IOException ioe){}
    }
    catch(IOException ioe)
    {
       try
       {
         output.writeInt(session.UPLOAD_UNSUCCESSFUL);
         //Close the stream
         if(fileOut != null)
           fileOut.close();
         output.flush();
       }
       catch(IOException io){}
    }
    catch(Exception e)
    {
        try
        {
          output.writeInt(session.UPLOAD_UNSUCCESSFUL);
          //Close the stream
          if(fileOut != null)
            fileOut.close();
          output.flush();
        }
        catch(IOException io){}
     }
   }

**************************************************************


Next, the uploadFile() method (client side):

private void uploadFile(String FileToPathOnServer, String
FileFromLocalDrive)
  {
    File myFile = null;
    //Show the connection icon on the interface
    ref.showConnectionIcon();

    //Tell the server where to put the uploaded file
    try
    {
      output.writeInt(PATH);
      if(ref.serverOS.equals("Windows"))
      {
        output.writeUTF(convertSingleBackwardSlash(FileToPathOnServer));
      }
      else
      {
        output.writeUTF(FileToPathOnServer);
      }
    }
    catch(IOException ioe){System.out.println("IOException\n");
ioe.printStackTrace();}

    if(getPlatform().equals("Windows"))
    {
      String temp = convertSingleBackwardSlash(FileFromLocalDrive);
      //System.out.println(temp);
      myFile = new File(temp);
    }
    else
    {
      myFile = new File(FileFromLocalDrive);
    }

    int fileLength = 0;

    //Access the file on local drive and start reading from it.
    try
    {
       fin = new FileInputStream(myFile);
       //tell the server how many bytes to expect
       try
       {
          fileLength = fin.available();
       }
       catch(IOException ioe){System.out.println("IOException\n");
ioe.printStackTrace();}

    }
    catch(FileNotFoundException
fnfe){System.out.println("FileNotFoundException\n");
fnfe.printStackTrace();}
    //Begin transfering the file at byte level
    try
    {
       //tell the server we're uploading a file
       output.writeInt(UPLOAD_FILE);
       /*The file size can quite possibly be quite large.
         So, we're going to set the array size to 128 bytes
         and keep sending data in chunks of 128 bytes.
       */
       output.writeInt(fileLength);
       System.out.println("Output filelength = " + fileLength);

       buf = new byte[128];

       //Wait or the signal to proceed before attempting to upload the
data.
       //We do this by invoking a worker thread which checks the
"proceed" and
       //"WebSpaceFull" flags every five seconds.
       //See request_workerThread class.
       //System.out.println("Calling timer functions.");

       ref.textLabel.setText("uploading " + myFile.getName());

       //Call the worker thread to finish the job!
       //timer.setByteArrayReference(buf, fileLength, fin); 
//<<<Ordinarily, I you just call these and let
       //timer.setThreadSuspended(false);		     //<<<the worker thread
finish up.
       

       //The rest here is just for testing purposes. Normally, this
would be in the 
       //request_workerThread class.
       while(true)
       {
          if(proceed)
            break;
       }

       ref.jProgressBar1.setMinimum(0);
       ref.jProgressBar1.setMaximum(fileLength);
       ref.jProgressBar1.setStringPainted(true);
       ref.jProgressBar1.setVisible(true);
       disableMenus();

       int n;
       while((n = fin.read(buf)) >= 0)
       {
          output.write(buf);
          ref.jProgressBar1.setValue(n);
       }
       output.write(buf);
       System.out.println(n);
       System.out.println("Finished writing out file");
       output.flush();
       ref.jProgressBar1.setVisible(false);
       enableMenus();
       proceed = false;//reset
       WebSpaceFull = false; //reset

       //End of test code.
    }
    catch(IOException ioe){System.out.println("IOException\n");
ioe.printStackTrace();}
    catch(Exception e)
    {
       System.out.println("Exception\n");
       e.printStackTrace();
       ref.jLabel1.setText("Status: Exception in method uploadFile - You
may have lost your connection.");
       enableMenus();
    }
    //Close the stream
    try
    {
      if(fin != null)
        fin.close();
    }
    catch(IOException ioe){System.out.println("IOException\n");
ioe.printStackTrace();}


  }

************************************************************

Finally, the following is the request_workerThread class. Keep in mind
that I use this class to handle both the uploading of only one file from
uploadFile() and the uploading of multiple files from uploadFiles().
uploadFiles() is almost identicle to uploadFile() except that it used a
for loop to iterate through multiple
selected files. Thus the reason why I'm testing for fileNames.

Obviously, there is going to have to be some refining here.

import java.io.*;

 
public class request_workerThread extends Thread
{
  private boolean threadSuspended = true; //default
  private int timeElapsed = 0;
  private request rq = null;
  private byte[] array;
  private String fileName;
  private int SizeOfFile = 0;
  private FileInputStream FileIn = null;


  public request_workerThread(request req)
  {
    //System.out.println("request_workerThread instantiated.");
    rq = req;
  }

  protected synchronized void setByteArrayReference(byte[] reference,
int fileSize, Object inputStream)
  {
    array = reference;
    SizeOfFile = fileSize;
    FileIn = (FileInputStream)inputStream;
    //System.out.println("reference to byte array set.");
  }

  protected synchronized void setFileName(String name)
  {
    fileName = name;
    //System.out.println("fileName " + name + " set.");
  }

  /**
   * This class extends class Thread, therefore we must overwrite the
run() method.
   */
  public void run()
  {
     while(true)
      {
         if(threadSuspended)
         {
            synchronized(this)
            {
               try
               {
                  while(threadSuspended)
                  {
                     //System.out.println("threadSuspended = true");
                     wait();
                  }
               }
               catch(IllegalMonitorStateException imse){}
               catch(InterruptedException ie){}
            }
         }

         try
         {
            Thread.sleep(5000);  //run a 5 second timer
         }
         catch(InterruptedException e){}

         //Record time elapsed.
         timeElapsed = timeElapsed + 5;
         //System.out.println("Elapsed time = " +
String.valueOf(timeElapsed) + " seconds.");

         //Check to see if the either flag has been set.
         //If not, after thirty seconds then put this thread to sleep
again.
         //System.out.println("proceed = " + rq.proceed + " WebSpaceFull
= " + rq.WebSpaceFull);
         if(rq.proceed || rq.WebSpaceFull)
         {
            try
            {
              if(rq.proceed)
              {
                //sending only one file
                if(fileName == null || fileName.equals(""))
                {
                  //send the server the contents of the file
                  //System.out.println("received signal to proceed with
upload");

                  rq.ref.jProgressBar1.setMinimum(0);
                  rq.ref.jProgressBar1.setMaximum(SizeOfFile);
                  rq.ref.jProgressBar1.setStringPainted(true);
                  rq.ref.jProgressBar1.setVisible(true);
                  rq.disableMenus();

                  int n;

                  while((n = FileIn.read(array)) >= 0)
                  {
                      rq.output.write(array);
                      rq.ref.jProgressBar1.setValue(n);
                  }

                  rq.output.flush();
                  rq.ref.jProgressBar1.setVisible(false);
                  rq.enableMenus();
                  rq.proceed = false; //reset
                  timeElapsed = 0; //reset
                  setThreadSuspended(true); //reset

                }
                else  //sending more than one file
                {
                  //send the server the contents of the file
                  //System.out.println("received signal to proceed with
upload");
                  rq.output.writeUTF(fileName);

                  rq.ref.jProgressBar1.setMinimum(0);
                  rq.ref.jProgressBar1.setMaximum(array.length);
                  rq.ref.jProgressBar1.setStringPainted(true);
                  rq.ref.jProgressBar1.setVisible(true);
                  for(int i = 0; i < array.length; i++)
                  {
                    rq.output.writeByte(array[i]);
                    rq.ref.jProgressBar1.setValue(i);
                  }

                  rq.output.flush();
                  rq.ref.jProgressBar1.setVisible(false);
                  fileName = ""; //reset
                  rq.proceed = false; //reset
                  timeElapsed = 0; //reset
                  rq.sendNextFile = true; //reset
                  setThreadSuspended(true); //reset

                }
              }
              else if(rq.WebSpaceFull)
              {
                //Don't send any data!
                //System.out.println("received signal to abort upload");
                //We need to set flag: sendNextFile = true
                //if processing multiple files for upload so that we can
                //exit out of both the while and for loops in
rq.uploadFiles().
                //uploadfiles() will also attempt to reset flag:
WebSpaceFull = false.
                if(!fileName.equals(""))
                {
                  rq.sendNextFile = true;//reset
                }
                rq.output.flush();
                timeElapsed = 0; //reset
                rq.WebSpaceFull = false; //reset
                setThreadSuspended(true); //reset
              }
            }
            catch(IOException ioe){ioe.printStackTrace();}
         }
         if(timeElapsed == 30)
         {
            timeElapsed = 0; //reset
            rq.ref.imageLabel.setIcon(rq.ref.blank);
            rq.ref.textLabel.setText("");
            rq.ref.jLabel1.setText("Status: Unable to complete File
Upload or File Save. Please try again.");
            rq.enableMenus();
            //System.out.println("Time elapsed is 30
seconds.\nrequest_workerThread is being reset to a suspended state.");
            /*There is a possibility that we'll have a time lapse of 30
seconds
             *and we're trying to upload multiple files. In this case,
since
             *request.uploadFiles() has a while loop in it, we need to
break
             *out of the while loop and the for loop. Therefore, we'll
set
             *both flags to true: WebSpaceFull and sendNextFile.
             */
            if(fileName != null && !fileName.equals(""))
            {
              rq.WebSpaceFull = true;//reset
              rq.sendNextFile = true;//reset
            }

            setThreadSuspended(true);
         }
      }
  }

  /**
   * Find out the state of threadSuspended.
   */
  public boolean getThreadSuspended()
  {
      return threadSuspended;
  }

  /**
   * Set the value of threadSuspended.
   * @param A boolean value.
   */
  public synchronized void setThreadSuspended(boolean value)
  {  //System.out.println("threadSuspended being set to " +
String.valueOf(value));
     threadSuspended = value;
     if(value == false)//we want to wake up this thread
        notify();
  }
}


Owen Green wrote:
> 
> "Alan Shiers" <ashiers@hfx.eastlink.ca> wrote in message
> news:3D233ADD.C365148D@hfx.eastlink.ca...
> > For some reason, when I split things up this way it generates this "Bad
> > file descriptor" error.  I still don't know why that is.
> 
> Could've been duplicating the FD's somewhere and getting confused? Are FD's
> ThreadLocal?
> 
> > Anyway, for the sake of expediency, I've cut out the use of the worker
> > thread for now and have placed all the code in the uploadFile() method.
> > Now, I don't get the "Bad file descriptor" error.
> >
> > However, now I'm faced with a new dilemma. The while loop hangs on the
> > server-side app!
> >
> > The client-side app definitely completes and exits the while loop, but
> > not on the server-side app.
> >
> > When I place a System.out.print(n + ", "); statement inside the loop on
> > the server-side app, I get:
> >
> > 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
> >
> > Then it just hangs there waiting to read in more. When I terminate the
> > server-side app the line continues to add a four on the end:
> >
> > 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 4,
> >
> > The next printlin statement tells me it finally closed the stream. But
> > only after I shut down the entire app.
> 
> Are you definately closing the files when you're done? e.g.
> 
> FileInputStream fis = null;
> try{
>   /* do stuff */
> }
> finally{
>   try{fis.close();}catch(IOException ioe){ioe.printStackTrace();}
> }
> 
> If you post your entire uploadFile() method (if its not too huge), it will be easier to see what's happening.
> 
> hth
> Owen
Technical Details
Message-ID: <3D248669.F2427A22@hfx.eastlink.ca>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-06!supernews.com!newsfeed.ision.net!ision!newsfeed.freenet.de!eusc.inter.net!newsfeed01.sul.t-online.de!t-online.de!dnews
References: <3D20CC5D.B70473C9@hfx.eastlink.ca> <MPG.178acb912dba8f7998b79d@newsgroups.borland.com> <3D21C1CA.F2D953E2@hfx.eastlink.ca> <3d21bb44_1@dnews> <3D21EC78.228A5CD3@hfx.eastlink.ca> <3d21e07b_2@dnews> <3D226288.1C7C905@hfx.eastlink.ca> <3d22ec28_1@dnews> <3D233ADD.C365148D@hfx.eastlink.ca> <3d245dff_2@dnews>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 1089d0,28eab50e784856ac
X-Google-Attributes: gid1089d0,public
X-Google-ArrivalTime: 2002-07-04 09:40:21 PST
Message-ID: <3D248669.F2427A22@hfx.eastlink.ca>
Date: Thu, 04 Jul 2002 13:31:21 -0400
From: Alan Shiers <ashiers@hfx.eastlink.ca>
Organization: Mustard Seed Software
X-Mailer: Mozilla 4.78 [en] (Win98; U)
X-Accept-Language: en
MIME-Version: 1.0
Newsgroups: borland.public.jbuilder.java.api
Subject: Re: OutOfMemoryError
References: <3D20CC5D.B70473C9@hfx.eastlink.ca> <MPG.178acb912dba8f7998b79d@newsgroups.borland.com> <3D21C1CA.F2D953E2@hfx.eastlink.ca> <3d21bb44_1@dnews> <3D21EC78.228A5CD3@hfx.eastlink.ca> <3d21e07b_2@dnews> <3D226288.1C7C905@hfx.eastlink.ca> <3d22ec28_1@dnews> <3D233ADD.C365148D@hfx.eastlink.ca> <3d245dff_2@dnews>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
NNTP-Posting-Host: 24.222.101.2
X-Trace: dnews 1025800124 24.222.101.2 (4 Jul 2002 09:28:44 -0700)
Lines: 572
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-06!supernews.com!newsfeed.ision.net!ision!newsfeed.freenet.de!eusc.inter.net!newsfeed01.sul.t-online.de!t-online.de!dnews