Example #1
0
def _allocate_popsno():
    """ allocate pops number 

    In order to prevent multiple AIPS instances from using the same POPS
    number, every AIPS instance creates a lock file in /tmp.  These lock
    files are named AIPSx.yyy, where x is the POPS number (in extended
    hex) and yyy is the process ID of the AIPS instance.
    Create a file in /tmp/AIPS_pops.pid to indicate this pops number is
    in use.
    """
    for popsno in range(1, 16):
        # In order to prevent a race, first create a lock file for
        # POPSNO.
        try:
            path = '/tmp/AIPS' + ehex(popsno, 1, 0) + '.' + str(os.getpid())
            fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644)
            os.close(fd)
        except:
            continue

        # Get a list of likely lock files and iterate over them.
        # Leave out our own lock file though.
        files = glob.glob('/tmp/AIPS' + ehex(popsno, 1, 0) + '.[0-9]*')
        files.remove(path)
        for file in files:
            # If I can't write it is probably not mine
            if not os.access(file, os.W_OK):
                #print "DEBUG write access failed for ",file
                break
            # If the part after the dot isn't an integer, it's not a
            # proper lock file.
            try:
                pid = int(file.split('.')[1])
            except:
                continue

            # Check whether the AIPS instance is still alive.
            try:
                os.kill(pid, 0)
            except:
                # The POPS number is no longer in use.  Try to clean
                # up the lock file.  This might fail though if we
                # don't own it.
                try:
                    os.unlink(file)
                except:
                    pass
            else:
                # The POPS number is in use.
                break
        else:
            # The POPS number is still free.
            return popsno

        # Clean up our own mess.
        os.unlink(path)

    raise RuntimeError("No free AIPS POPS number available on this system")
Example #2
0
def _free_popsno(popsno):
    """ Deallocate pops number
    
    Unlinks /tmp/ObitScript_pops file
    """
    path = '/tmp/ObitScript' + ehex(popsno, 1, 0) + '.' + str(os.getpid())
    os.unlink(path)
Example #3
0
    def messages(self, tid):
        """Return task's messages.
        
        Return a list of messages each as a tuple (1, message)
        tid   = Task id in pid table of process
        """

        # Make sure we read the messages, even if we throw them away
        # later to prevent the task from blocking.
        messages = Task.messages(self, tid)
        #print "Raw",messages

        # Check that tid in bounds
        #if tid>len(self._popsno):
        #    print "DEBUG Proxy/AIPSTask", messages, tid, len(self._popsno)
        #    return messages

        # Convert into list of lines
        tmessage = []
        for msg in messages:
            lmess = msg.splitlines(True)
            for mm in lmess:
                tmessage.append(mm)

        # Strip out all formal messages.
        start = '%-5s%d' % (self._params[tid].name.upper(), self._popsno[tid])
        lmessages = [msg for msg in tmessage if msg.startswith(start)]
        #print "Filtered",lmessages
        pmessages = [msg for msg in tmessage if not msg.startswith(start)]
        #print "Print",pmessages

        # These messages will be looked up in the AIPS message log
        #messages = [(1, msg) for msg in lmessages]
        messages = []

        user = ehex(self._userno[tid], 3, 0)
        ms_name = os.environ['DA01'] + '/MS' + AIPS.revision \
                  + user + '000.' + user + ';'
        ms_file = open(ms_name, mode='r')

        (msgno,) = struct.unpack('i', ms_file.read(4))
        while self._msgno[tid] < msgno:
            (task, popsno, priority, msg) = \
                   self.__read_message(ms_file, self._msgno[tid])
            # Filter
            if popsno == self._popsno[tid]:
                messages.append((priority, '%-5s%d: %s\n' % (task, popsno, msg)))
                pass
            self._msgno[tid] += 1
            continue

        ms_file.close()
        # Add "print" messages
        if len(pmessages)>0:
            for msg in pmessages:
                messages.append((1,msg))
        #print "returned messages",messages
        return messages
Example #4
0
    def spawn(self, name, version, userno, msgkill, isbatch, input_dict):
        """Start the script.in an externak ObitTalk
        
        Writes script test into temporary file in /tmp and executes ObitTalk
        asynchronously returning immediately.
        Messages must be  retrieved calling messages.
        name        script name
        version     version of any AIPS tasks
        userno      AIPS user number
        msgkill     AIPStask msgkill level,
        isbatch     True if this is a batch process
        input_dict  Input info as dictionary
        Returns script id
        """

        popsno = _allocate_popsno()
        index = popsno - 1
        self.name = name
        self.userno = userno

        try:
            # Construct the environment for the script.  
            # Set AIPS and FITS directory variables
            env = os.environ.copy()
            # AIPS directories
            i = 0
            for dirname in input_dict["AIPSDirs"]:
                i = i+1
                area = 'DA' + ehex(i, 2, '0')
                env[area] = dirname
            # end AIPS dirs
            # FITS directories
            i = 0
            for dirname in input_dict["FITSDirs"]:
                i = i+1
                if i==1:
                    area = "FITS"
                else:
                    area = 'FITS' + ehex(i, 2, '0')
                env[area] = dirname
            # End FITS Dirs
            
            # print "script environment",env
            # print "PYTHONPATH",env["PYTHONPATH"]

            # Script text file
            sc_name = "/tmp/" + name+ "Script." + str(popsno)+".py"
            
            # Write script to file
            self.__write_script (self.name, userno, popsno, sc_name, input_dict)

            # If debugging add a link to the input file to preserve it.
            if input_dict['debug']:
                tmpDebug = "/tmp/" + name+ "Script." + str(popsno)+"Dbg.py"
                if os.access(tmpDebug, os.F_OK):
                    os.unlink(tmpDebug)        # Remove any old version file.
                os.link(sc_name, tmpDebug) # Add new link.
                # Tell about it.
                print("Saving copy of Obit task input in " + tmpDebug)
            
            # Start script in separate ObitTalk process.
            path = 'ObitTalk'
            tid = Task.spawn(self, path, ["ObitTalk", sc_name], env)
            
        except Exception as exception:
            _free_popsno(popsno)
            raise exception
        
        self._popsno[tid]  = popsno
        self._userno[tid]  = userno
        self._msgkill[tid] = msgkill
        self._msgno[tid]   = 0

        return tid
Example #5
0
 def _open(self, userno):
     user = ehex(userno, 3, 0)
     ms_name = os.environ['DA01'] + '/MS' + AIPS.revision \
               + user + '000.' + user + ';'
     return open(ms_name, mode='r+')
Example #6
0
    def spawn(self, name, version, userno, msgkill, isbatch, input_dict):
        """Start the task.
        
        Writes task input parameters in theTD file and starts the task
        asynchronously returning immediately.
        Messages must be  retrieved calling messages.
        Attempts to use singel hardcoded AIPS TV
        name        task name
        version     version of task
        userno      AIPS user number
        msgkill     AIPS msgkill level,
        isbatch     True if this is a batch process
        input_dict  Input parameters as dictionary
        Returns task id
        """

        params = _AIPSTaskParams(name, version)
        popsno = _allocate_popsno()
        index = popsno - 1
        try:
            # A single hardcoded TV will do until support for multiple
            # TVs is implemented.
            ntvdev = 1

            # Construct the environment for the task.  For the 'infile',
            # 'outfile' and 'outprint' adverbs, we split off the directory
            # component of the pathname and use that as the area.
            env = os.environ.copy()
            area = 'a'
            for adverb in self._file_adverbs:
                if adverb in input_dict:
                    assert (ord(area) <= ord('z'))
                    dirname = os.path.dirname(input_dict[adverb])
                    if dirname:
                        if not os.path.isdir(dirname):
                            msg = "Directory '%s' does not exist" % dirname
                            raise RuntimeError(msg)
                        env[area] = dirname
                        basename = os.path.basename(input_dict[adverb])
                        input_dict[adverb] = area + ':' + basename
                        area = chr(ord(area) + 1)
                        pass
                    pass
                continue
            # Send output to the TV running on this machine.
            env['TVDEV' + ehex(ntvdev, 2, 0)] = 'sssin:localhost'
            # DEBUG
            #print "aips environment",env

            td_name = os.environ['DA00'] + '/TD' + AIPS.revision + '000004;'
            td_file = open(td_name, mode='r+b')
            td_file.seek(index * 20)
            td_file.write(
                struct.pack('8s', six.ensure_binary(name.upper().ljust(8))))
            td_file.write(struct.pack('l', -999))
            td_file.write(struct.pack('2l', 0, 0))
            td_file.seek(1024 + index * 4096)
            td_file.write(struct.pack('i', userno))
            td_file.write(struct.pack('i', ntvdev))
            td_file.write(struct.pack('i', 0))
            td_file.write(struct.pack('i', msgkill + 32000 - 1))
            td_file.write(struct.pack('i', isbatch))
            td_file.write(struct.pack('i', 0))
            td_file.write(struct.pack('2i', 0, 0))
            td_file.write(struct.pack('f', 1.0))
            td_file.write(struct.pack('4s', b'    '))
            for adverb in params.input_list:
                self.__write_adverb(params, td_file, adverb,
                                    input_dict[adverb])
                continue
            td_file.close()
            # Pass aips directories
            i = 0
            for dir in input_dict["AIPSdirs"]:
                i += 1
                daname = "DA" + ehex(i, 2, 0)
                if not name in env:
                    env[daname] = dir

            # Create the message file if necessary and record the
            # number of messages currently in it.
            user = ehex(userno, 3, 0)
            if 'DA01' in os.environ:
                # Use DA01 from environment if given
                da01 = os.environ['DA01']
            else:  # Else from AIPSdirs passed.
                da01 = input_dict["AIPSdirs"][0]
                # Grumble, grumble
                os.environ['DA01'] = da01
                cmd = "export DA01=" + da01  # shell environment
                z = os.system(cmd)

            ms_name = da01 + '/MS' + AIPS.revision \
                      + user + '000.' + user + ';'
            if not os.path.exists(ms_name):
                ms_file = open(ms_name, mode='w')
                ms_file.truncate(1024)
                ms_file.close()
                os.chmod(ms_name, 0o664)
                pass
            ms_file = open(ms_name, mode='rb')
            (msgno, ) = struct.unpack('i', ms_file.read(4))
            ms_file.close()
            path = params.version + '/' + os.environ['ARCH'] + '/LOAD/' \
                   + name.upper() + ".EXE"
            tid = Task.spawn(self, path, [name.upper() + str(popsno)], env)

        except Exception as exception:
            _free_popsno(popsno)
            raise exception

        self._params[tid] = params
        self._popsno[tid] = popsno
        self._userno[tid] = userno
        self._msgkill[tid] = msgkill
        self._msgno[tid] = msgno
        return tid