Example #1
0
    def _collect(self, limit):
        size_x, size_y = (1280, 1024)
        handle, snapshot_file = tempfile.mkstemp('.png')
        command = 'fswebcam -q -r %dx%d --png 9 -D 1 -S 7 --no-banner %s' % (size_x, size_y, snapshot_file)
        subprocess.check_call(command, shell=True)
        os.close(handle)
        memdam.log().debug("Saved " + snapshot_file + " (Size: " + str(size_x) + " x " + str(size_y) + ")")

        if os.path.getsize(snapshot_file) <= 0:
            memdam.log().warn("Failed to capture webcam image")
            os.remove(snapshot_file)
            return []

        if self._is_similar_to_last_image(snapshot_file):
            os.remove(snapshot_file)
            return []

        copied_location = memdam.common.utils.make_temp_path()
        shutil.copy(snapshot_file, copied_location)
        if self._last_image != None:
            os.remove(self._last_image)
        self._last_image = copied_location

        snapshot = self._save_file(snapshot_file, consume_file=True)
        return [memdam.common.event.new(u"com.memdam.webcam", data__file=snapshot)]
Example #2
0
 def _is_similar_to_last_image(self, screenshot):
     '''
     :param screenshot: the image to check for similarity against our previous capture
     :type  screenshot: string(path)
     :returns: True iff the image is sufficiently similar to the last one we took.
     :rtype: boolean
     '''
     if self._last_image is None:
         return False
     difference = memdam.common.image.rmsdiff(Image.open(self._last_image), Image.open(screenshot))
     memdam.log().debug("SNAPSHOT DIFFERENCE=%s", difference)
     return difference < self._threshold
Example #3
0
def handle_errors(err):
    """
    Generic JSON error handler. Adds a bit more color to what happened.
    """
    exc_info = sys.exc_info()
    trace_data = '\n'.join(traceback.format_exception(*exc_info))
    if isinstance(err, werkzeug.exceptions.HTTPException):
        response_data = dict(description=err.description)
        status_code = err.code
    else:
        response_data = dict(description=str(err))
        status_code = 500
    response_data['code'] = status_code
    response_data['failed'] = True
    response_data['trace'] = trace_data
    memdam.log().info("Request failed: " + str(response_data))
    return flask.make_response(flask.jsonify(response_data), status_code)
Example #4
0
def report(e):
  exc_info = sys.exc_info()

  htmlContent = get_error_html(e, exc_info)
  textContent = '\n'.join(traceback.format_exception(*exc_info))

  memdam.log().error(textContent)
  if memdam.config.mandrill_key == None:
    filename = "/tmp/python_%s_%s_error.html" % \
               (os.getpid(), threading.current_thread().ident)
    html_file = open(filename, "wb")
    html_file.write(htmlContent)
    html_file.close()
    webbrowser.open_new_tab("file://%s" % (filename))
    #just so that it doesn't pop up a million windows
    sys.exit()
  else:
    send_email(memdam.config.mandrill_key, textContent, htmlContent)
Example #5
0
 def _process(self, work_id):
     memdam.log().info("Processing event " + str(work_id))
     event = self._event_source.get(work_id)
     for field, blob_ref in event.blob_ids:
         memdam.log().info("Processing blob " + str(work_id))
         temp_file = memdam.common.utils.make_temp_path()
         try:
             #TODO: someday, can check for existence in dest first, so that we don't have to re-upload files. Maybe ensure etag or something
             self._blob_source.get_data_to_file(blob_ref, temp_file)
         except memdam.blobstore.api.MissingBlob:
             #check that it exists at the destination at least:
             assert self._blob_dest.exists(blob_ref), "Fail. Tried to synchronize blob %s for event %s but there is no data for it?" % (blob_ref, work_id)
         self._blob_dest.set_data_from_file(blob_ref, temp_file)
         os.remove(temp_file)
     self._event_dest.save([event])
     self._event_source.delete(event.id__id)
     for field, blob_ref in event.blob_ids:
         self._blob_source.delete(blob_ref)
Example #6
0
 def _snapshot_func(self):
     '''Needs to be called from the main thread so that it can take a screenshot of the desktop'''
     try:
         import PyQt4.QtGui
         handle, screenshot_file = tempfile.mkstemp(".png")
         PyQt4.QtGui.QPixmap.grabWindow(PyQt4.QtGui.QApplication.desktop().winId()).save(screenshot_file, 'png')
         try:
             os.close(handle)
         except Exception, e:
             memdam.log().warn("Failed to close this file handle %s because %s" % (handle, e))
         memdam.log().debug("Saved screenshot to " + screenshot_file)
         if self._is_similar_to_last_image(screenshot_file):
             os.remove(screenshot_file)
             return []
         copied_location = memdam.common.utils.make_temp_path()
         shutil.copy(screenshot_file, copied_location)
         if self._last_image != None:
             os.remove(self._last_image)
         self._last_image = copied_location
         screenshot = self._save_file(screenshot_file, consume_file=True)
         return [memdam.common.event.new(u"com.memdam.screenshot", data__file=screenshot)]
Example #7
0
 def _collect(self, limit):
     if limit <= 0:
         memdam.log().error("SamplingCollector %s was skipped!" % (self))
     else:
         return self.sample()
Example #8
0
def _print_some_statements(num):
    """Print some statements and exit"""
    for i in range(0, num):
        memdam.log().info("log " + str(i))
        time.sleep(0.3)
Example #9
0
 def save(self, events):
     memdam.log().debug("Saving events")
     sorted_events = sorted(events, key=lambda x: x.namespace)
     for namespace, grouped_events in itertools.groupby(sorted_events, lambda x: x.namespace):
         table_name = namespace_to_table_name(namespace)
         self._save_events(list(grouped_events), table_name)
Example #10
0
    def _save_events(self, events, table_name):
        """
        Save all events of the same type to the database at once
        """
        memdam.log().debug("Saving %s events to %s" % (len(events), table_name))
        if len(events) <= 0:
            return
        assert SqliteColumn.SQL_NAME_REGEX.match(table_name), "Invalid name for table: %s" % (table_name)

        key_names = set()
        for event in events:
            for key in event.keys:
                key_names.add(key)
        #certain key names are ignored because they are stored implicity in the location of
        #this database (user, namespace)
        for reserved_name in ("type__namespace", "user__id"):
            if reserved_name in key_names:
                key_names.remove(reserved_name)

        should_update_columns = True
        if self.folder != ":memory:":
            #does table not exist?
            db_file = os.path.join(self.folder, table_name + Eventstore.EXTENSION)
            if not os.path.exists(db_file):
                #try to acquire lock
                lock_file = os.path.join(self.folder, table_name + Eventstore.LOCK_EXTENSION)
                lock = lockfile.LockFile(lock_file)
                with lock:
                    #two possible scenarios:
                    #1. we got the lock AFTER someone else, who already made the table:
                    if os.path.exists(db_file):
                        #TODO: move this somewhere more sensible
                        try:
                            os.remove(lock)
                        except:
                            pass
                    #2. we got the lock BEFORE anyone else, so we're responsible for making the table:
                    else:
                        should_update_columns = False
                        #make the table and create the columns
                        temp_db_file = os.path.join(self.folder, table_name + Eventstore.CREATE_TABLE_EXTENSION)
                        self._create_database(table_name, key_names, temp_db_file)
                        #move the file back to it's regular location
                        os.rename(temp_db_file, db_file)
                        #TODO: move this somewhere more sensible
                        try:
                            os.remove(lock)
                        except:
                            pass

        conn = self._connect(table_name, read_only=False)
        if should_update_columns:
            def update_columns():
                cur = conn.cursor()
                existing_columns = self._query_existing_columns(cur, table_name)
                required_columns = self._generate_columns(cur, key_names, table_name)
                self._update_columns(cur, existing_columns, required_columns)
            #TODO: use the locking approach for updating as well as creating?
            execute_with_retries(update_columns, 5)

        cur = conn.cursor()
        cur.execute("BEGIN EXCLUSIVE")
        self._insert_events(cur, events, key_names, table_name)
        conn.commit()